This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

Changeset 9814 for ps


Ignore:
Timestamp:
07/13/11 01:48:05 (13 years ago)
Author:
philip
Message:

Graphics optimisations and features from eihrul.
Add shadow filtering (PCF) option.
Fix ugly shadow saturation in old lighting mode.
Fix fancy water shader.
Fix camera matrix computation.
Support scissoring of camera frustum.
Optimise vertex skinning.
Inline various matrix functions.
Support filtering of the list of submitted models before a rendering pass, for more precise culling.
Optimise water renderer (fixes #721, based on patch by ortalo).
Use scissoring when generating reflection/refraction textures.
Skip reflection/refraction texture generation when no water is visible.
Render alpha-blended objects differently (fixes #434).
Reduce shadow swimming effects.

Location:
ps/trunk
Files:
48 edited

Legend:

Unmodified
Added
Removed
  • ps/trunk/binaries/data/config/default.cfg

    r9791 r9814  
    3030fancywater = true
    3131shadows = true
     32shadowpcf = true
    3233vsync = false
    3334
  • ps/trunk/binaries/data/mods/public/gui/session/menu.js

    r8719 r9814  
    1616{
    1717    var settings = getGUIObjectByName("settingsDialogPanel");
    18     g_SessionDialog.open("Settings", null, settings, 340, 224, null);
     18    g_SessionDialog.open("Settings", null, settings, 340, 252, null);
    1919}
    2020
  • ps/trunk/binaries/data/mods/public/gui/session/session.xml

    r9791 r9814  
    301301            sprite="genericPanel"
    302302            type="image"
    303             size="50%-180 50%-200 50%+180 50%+50"
     303            size="80%-180 50%-200 50%+180 50%+50"
    304304            hidden="true"
    305305            z="30"
     
    311311                <action on="Press">renderer.shadows = this.checked;</action>
    312312            </object>   
    313                
     313           
     314            <!-- Settings / Shadow PCF -->
     315            <object size="0 35 100%-80 60" type="text" style="settingsText" ghost="true">Enable Shadow Filtering</object>
     316            <object name="shadowPCFCheckbox" size="100%-56 40 100%-30 65" type="checkbox" style="wheatCrossBox" checked="true">
     317                <action on="Load">if (renderer.shadowPCF) this.checked = true; else this.checked = false;</action>
     318                <action on="Press">renderer.shadowPCF = this.checked;</action>
     319            </object>
     320   
    314321            <!-- Settings / Water -->
    315             <object size="0 35 100%-80 60" type="text" style="settingsText" ghost="true">Enable Water Reflections</object>
    316             <object name="fancyWaterCheckbox" size="100%-56 40 100%-30 65"  type="checkbox" style="wheatCrossBox" checked="true">
     322            <object size="0 60 100%-80 85" type="text" style="settingsText" ghost="true">Enable Water Reflections</object>
     323            <object name="fancyWaterCheckbox" size="100%-56 65 100%-30 90"  type="checkbox" style="wheatCrossBox" checked="true">
    317324                <action on="Load">if (renderer.fancyWater) this.checked = true; else this.checked = false;</action>
    318325                <action on="Press">renderer.fancyWater = this.checked;</action>
     
    320327               
    321328            <!-- Settings / Music-->
    322             <object size="0 60 100%-80 85" type="text" style="settingsText" ghost="true">Enable Music</object>
    323             <object size="100%-56 65 100%-30 90" type="checkbox" style="wheatCrossBox" checked="true">
     329            <object size="0 85 100%-80 110" type="text" style="settingsText" ghost="true">Enable Music</object>
     330            <object size="100%-56 90 100%-30 115" type="checkbox" style="wheatCrossBox" checked="true">
    324331                <action on="Press">if (this.checked) startMusic(); else stopMusic();</action>
    325332            </object>
    326333               
    327334            <!-- Settings / Dev Overlay -->
    328             <object size="0 85 100%-80 110" type="text" style="settingsText" ghost="true">Developer Overlay</object>
    329                 <object size="100%-56 90 100%-30 115" type="checkbox" style="wheatCrossBox" checked="false">
     335            <object size="0 110 100%-80 135" type="text" style="settingsText" ghost="true">Developer Overlay</object>
     336                <object size="100%-56 115 100%-30 140" type="checkbox" style="wheatCrossBox" checked="false">
    330337                <action on="Press">toggleDeveloperOverlay();</action>
    331338            </object>
  • ps/trunk/binaries/data/mods/public/hwdetect/hwdetect.js

    r9308 r9814  
    143143    var disable_s3tc = undefined;
    144144    var disable_shadows = undefined;
     145    var disable_shadowpcf = undefined;
    145146    var disable_fancywater = undefined;
    146147    var override_renderpath = undefined;
     
    213214    {
    214215        disable_shadows = true;
     216        disable_shadowpcf = true;
    215217    }
    216218
     
    223225    {
    224226        disable_fancywater = true;
     227        disable_shadowpcf = true;
    225228    }
    226229
     
    239242        "disable_s3tc": disable_s3tc,
    240243        "disable_shadows": disable_shadows,
     244        "disable_shadowpcf": disable_shadowpcf,
    241245        "disable_fancywater": disable_fancywater,
    242246        "override_renderpath": override_renderpath,
     
    270274        Engine.SetDisableShadows(output.disable_shadows);
    271275
     276    if (output.disable_shadowpcf !== undefined)
     277        Engine.SetDisableShadowPCF(output.disable_shadowpcf);
     278
    272279    if (output.disable_fancywater !== undefined)
    273280        Engine.SetDisableFancyWater(output.disable_fancywater);
  • ps/trunk/binaries/data/mods/public/hwdetect/test.js

    r9308 r9814  
    3030
    3131    var disabled = [];
    32     for each (var d in ["disable_audio", "disable_s3tc", "disable_shadows", "disable_fancywater", "override_renderpath"])
     32    for each (var d in ["disable_audio", "disable_s3tc", "disable_shadows", "disable_shadowpcf", "disable_fancywater", "override_renderpath"])
    3333        if (output[d] !== undefined)
    3434            disabled.push(d+"="+output[d])
  • ps/trunk/binaries/data/mods/public/shaders/model_common.fp

    r9142 r9814  
    2020PARAM shadingColor = program.local[1];
    2121PARAM ambient = program.local[2];
     22
     23#ifdef USE_SHADOW_PCF
     24  PARAM shadowOffsets1 = program.local[3];
     25  PARAM shadowOffsets2 = program.local[4];
     26  TEMP offset;
     27#endif
    2228
    2329TEMP tex;
     
    4349#ifdef USE_SHADOW
    4450  #ifdef USE_FP_SHADOW
    45     TEX temp, fragment.texcoord[1], texture[1], SHADOW2D;
     51    #ifdef USE_SHADOW_PCF
     52      MOV offset.zw, fragment.texcoord[1];
     53      ADD offset.xy, fragment.texcoord[1], shadowOffsets1;
     54      TEX temp.x, offset, texture[1], SHADOW2D;
     55      ADD offset.xy, fragment.texcoord[1], shadowOffsets1.zwzw;
     56      TEX temp.y, offset, texture[1], SHADOW2D;
     57      ADD offset.xy, fragment.texcoord[1], shadowOffsets2;
     58      TEX temp.z, offset, texture[1], SHADOW2D;
     59      ADD offset.xy, fragment.texcoord[1], shadowOffsets2.zwzw;
     60      TEX temp.w, offset, texture[1], SHADOW2D;
     61      DP4 temp, temp, 0.25;
     62    #else
     63      TEX temp, fragment.texcoord[1], texture[1], SHADOW2D;
     64    #endif
    4665  #else
    4766    TEX tex, fragment.texcoord[1], texture[1], 2D;
     
    4968    SGE temp, tex.x, temp.z;
    5069  #endif
    51   MUL diffuse.rgb, fragment.color, 2.0;
    52   MAD_MAYBE_SAT temp.rgb, diffuse, temp, ambient;
     70  #ifdef CLAMP_LIGHTING
     71    MAD_SAT diffuse.rgb, fragment.color, 2.0, ambient;
     72    LRP temp.rgb, temp, diffuse, ambient;
     73  #else
     74    MUL diffuse.rgb, fragment.color, 2.0;
     75    MAD temp.rgb, diffuse, temp, ambient;
     76  #endif
    5377  MUL color.rgb, color, temp;
    5478#else
  • ps/trunk/binaries/data/mods/public/shaders/model_common.xml

    r9142 r9814  
    2020        <uniform name="shadingColor" loc="1" type="vec3"/>
    2121        <uniform name="ambient" loc="2" type="vec3"/>
     22        <uniform name="shadowOffsets1" loc="3" type="vec4"/>
     23        <uniform name="shadowOffsets2" loc="4" type="vec4"/>
    2224    </fragment>
    2325
  • ps/trunk/binaries/data/mods/public/shaders/model_common_instancing.xml

    r9142 r9814  
    2323        <uniform name="shadingColor" loc="1" type="vec3"/>
    2424        <uniform name="ambient" loc="2" type="vec3"/>
     25        <uniform name="shadowOffsets1" loc="3" type="vec4"/>
     26        <uniform name="shadowOffsets2" loc="4" type="vec4"/>
    2527    </fragment>
    2628
  • ps/trunk/binaries/data/mods/public/shaders/terrain_base.xml

    r9123 r9814  
    1414
    1515        <uniform name="ambient" loc="0" type="vec3"/>
     16        <uniform name="shadowOffsets1" loc="2" type="vec4"/>
     17        <uniform name="shadowOffsets2" loc="3" type="vec4"/>
    1618    </fragment>
    1719
  • ps/trunk/binaries/data/mods/public/shaders/terrain_blend.xml

    r9123 r9814  
    1717
    1818        <uniform name="ambient" loc="0" type="vec3"/>
     19        <uniform name="shadowOffsets1" loc="2" type="vec4"/>
     20        <uniform name="shadowOffsets2" loc="3" type="vec4"/>
    1921    </fragment>
    2022
  • ps/trunk/binaries/data/mods/public/shaders/terrain_common.fp

    r9142 r9814  
    1818#ifdef DECAL
    1919  PARAM shadingColor = program.local[1];
     20#endif
     21
     22#ifdef USE_SHADOW_PCF
     23  PARAM shadowOffsets1 = program.local[2];
     24  PARAM shadowOffsets2 = program.local[3];
     25  TEMP offset;
    2026#endif
    2127
     
    4450#ifdef USE_SHADOW
    4551  #ifdef USE_FP_SHADOW
    46     TEX temp, fragment.texcoord[2], texture[2], SHADOW2D;
     52    #ifdef USE_SHADOW_PCF
     53      MOV offset.zw, fragment.texcoord[2];
     54      ADD offset.xy, fragment.texcoord[2], shadowOffsets1;
     55      TEX temp.x, offset, texture[2], SHADOW2D;
     56      ADD offset.xy, fragment.texcoord[2], shadowOffsets1.zwzw;
     57      TEX temp.y, offset, texture[2], SHADOW2D;
     58      ADD offset.xy, fragment.texcoord[2], shadowOffsets2;
     59      TEX temp.z, offset, texture[2], SHADOW2D;
     60      ADD offset.xy, fragment.texcoord[2], shadowOffsets2.zwzw;
     61      TEX temp.w, offset, texture[2], SHADOW2D;
     62      DP4 temp, temp, 0.25;
     63    #else
     64      TEX temp, fragment.texcoord[2], texture[2], SHADOW2D;
     65    #endif
    4766  #else
    4867    TEX tex, fragment.texcoord[2], texture[2], 2D;
     
    5069    SGE temp, tex.x, temp.z;
    5170  #endif
    52   MUL diffuse.rgb, fragment.color, 2.0;
    53   MAD_MAYBE_SAT temp.rgb, diffuse, temp, ambient;
     71  #ifdef CLAMP_LIGHTING
     72    MAD_SAT diffuse.rgb, fragment.color, 2.0, ambient;
     73    LRP temp.rgb, temp, diffuse, ambient;
     74  #else
     75    MUL diffuse.rgb, fragment.color, 2.0;
     76    MAD temp.rgb, diffuse, temp, ambient;
     77  #endif
    5478  MUL color.rgb, color, temp;
    5579#else
  • ps/trunk/binaries/data/mods/public/shaders/terrain_decal.xml

    r9142 r9814  
    1717        <uniform name="ambient" loc="0" type="vec3"/>
    1818        <uniform name="shadingColor" loc="1" type="vec3"/>
     19        <uniform name="shadowOffsets1" loc="2" type="vec4"/>
     20        <uniform name="shadowOffsets2" loc="3" type="vec4"/>
    1921    </fragment>
    2022
  • ps/trunk/binaries/data/mods/public/shaders/water_high.fs

    r8882 r9814  
    1717
    1818varying vec3 worldPos;
    19 varying float w;
    2019varying float waterDepth;
    2120
     
    2524    float ndotl, ndoth, ndotv;
    2625    float fresnel;
    27     float myMurkiness;      // Murkiness and tint at this pixel (tweaked based on lighting and depth)
    2826    float t;                // Temporary variable
    2927    vec2 reflCoords, refrCoords;
     
    4038    ndotv = dot(n, v);
    4139   
    42     myMurkiness = murkiness * min(waterDepth / fullDepth, 1.0);
    43    
    4440    fresnel = pow(1.0 - ndotv, 0.8);    // A rather random Fresnel approximation
    4541   
    46     refrCoords = 0.5 * (gl_TexCoord[2].xy / gl_TexCoord[2].w) + 0.5;    // Unbias texture coords
    47     refrCoords -= 0.8 * waviness * n.xz / w;        // Refractions can be slightly less wavy
    48    
    49     reflCoords = 0.5 * (gl_TexCoord[1].xy / gl_TexCoord[1].w) + 0.5;    // Unbias texture coords
    50     reflCoords += waviness * n.xz / w;
     42    refrCoords = (0.5*gl_TexCoord[2].xy - 0.8*waviness*n.xz) / gl_TexCoord[2].w + 0.5;  // Unbias texture coords
     43    reflCoords = (0.5*gl_TexCoord[1].xy + waviness*n.xz) / gl_TexCoord[1].w + 0.5;  // Unbias texture coords
    5144   
    5245    reflColor = mix(texture2D(reflectionMap, reflCoords).rgb, sunColor * reflectionTint,
     
    5447   
    5548    refrColor = (0.5 + 0.5*ndotl) * mix(texture2D(refractionMap, refrCoords).rgb, sunColor * tint,
    56                     myMurkiness);
     49                    murkiness * clamp(waterDepth / fullDepth, 0.0, 1.0)); // Murkiness and tint at this pixel (tweaked based on lighting and depth)
    5750   
    5851    specular = pow(max(0.0, ndoth), shininess) * sunColor * specularStrength;
  • ps/trunk/binaries/data/mods/public/shaders/water_high.vs

    r8882 r9814  
    22uniform mat4 refractionMatrix;
    33uniform mat4 losMatrix;
    4 uniform vec4 translation;
    5 
    6 attribute float vertexDepth;
     4uniform float repeatScale;
     5uniform vec2 translation;
    76
    87varying vec3 worldPos;
    9 varying float w;
    108varying float waterDepth;
    119
     
    1311{
    1412    worldPos = gl_Vertex.xyz;
    15     waterDepth = vertexDepth;
    16     gl_TexCoord[0] = gl_MultiTexCoord0 + translation;
     13    waterDepth = dot(gl_Color.xyz, vec3(255.0, -255.0, 1.0));
     14    gl_TexCoord[0].st = gl_Vertex.xz*repeatScale + translation;
    1715    gl_TexCoord[1] = reflectionMatrix * gl_Vertex;      // projective texturing
    18     gl_TexCoord[2] = reflectionMatrix * gl_Vertex;
     16    gl_TexCoord[2] = refractionMatrix * gl_Vertex;
    1917    gl_TexCoord[3] = losMatrix * gl_Vertex;
    20     w = gl_TexCoord[1].w;
    2118    gl_Position = ftransform();
    2219}
  • ps/trunk/source/graphics/Camera.cpp

    r9141 r9814  
    3535#include "renderer/WaterManager.h"
    3636
    37 CCamera::CCamera ()
     37CCamera::CCamera()
    3838{
    3939    // set viewport to something anything should handle, but should be initialised
     
    4545}
    4646
    47 CCamera::~CCamera ()
    48 {
    49 }
    50 
    51 void CCamera::SetProjection (float nearp, float farp, float fov)
     47CCamera::~CCamera()
     48{
     49}
     50
     51void CCamera::SetProjection(float nearp, float farp, float fov)
    5252{
    5353    m_NearPlane = nearp;
     
    5555    m_FOV = fov;
    5656
    57     float Aspect = (float)m_ViewPort.m_Width/(float)m_ViewPort.m_Height;
    58 
    59     float w = tanf (m_FOV*0.5f*Aspect);
    60     float h = tanf (m_FOV*0.5f);
     57    float aspect = (float)m_ViewPort.m_Width/(float)m_ViewPort.m_Height;
     58    float f = 1.0f/tanf(m_FOV/2);
    6159
    6260    m_ProjMat.SetZero ();
    63     m_ProjMat._11 = 1/w;
    64     m_ProjMat._22 = 1/h;
    65     m_ProjMat._33 = (m_FarPlane+m_NearPlane)/(m_FarPlane-m_NearPlane);
    66     m_ProjMat._34 = -2*m_FarPlane*m_NearPlane/(m_FarPlane-m_NearPlane);
     61    m_ProjMat._11 = f/aspect;
     62    m_ProjMat._22 = f;
     63    m_ProjMat._33 = -(m_FarPlane+m_NearPlane)/(m_NearPlane-m_FarPlane);
     64    m_ProjMat._34 = 2*m_FarPlane*m_NearPlane/(m_NearPlane-m_FarPlane);
    6765    m_ProjMat._43 = 1.0f;
    6866}
    6967
    70 void CCamera::SetProjectionTile (int tiles, int tile_x, int tile_y)
    71 {
    72     float Aspect = (float)m_ViewPort.m_Width/(float)m_ViewPort.m_Height;
    73 
    74     float w = tanf (m_FOV*0.5f*Aspect) / tiles;
    75     float h = tanf (m_FOV*0.5f) / tiles;
    76 
    77     m_ProjMat._11 = 1/w;
    78     m_ProjMat._22 = 1/h;
     68void CCamera::SetProjectionTile(int tiles, int tile_x, int tile_y)
     69{
     70
     71    float aspect = (float)m_ViewPort.m_Width/(float)m_ViewPort.m_Height;
     72    float f = 1.0f/tanf(m_FOV/2);
     73
     74    m_ProjMat._11 = tiles*f/aspect;
     75    m_ProjMat._22 = tiles*f;
    7976    m_ProjMat._13 = -(1-tiles + 2*tile_x);
    8077    m_ProjMat._23 = -(1-tiles + 2*tile_y);
     
    8481//everytime the view or projection matrices are
    8582//altered.
    86 void CCamera::UpdateFrustum ()
     83void CCamera::UpdateFrustum(const CBound& scissor)
    8784{
    8885    CMatrix3D MatFinal;
     
    9390    MatFinal = m_ProjMat * MatView;
    9491
    95     //get the RIGHT plane
    96     m_ViewFrustum.SetNumPlanes (6);
    97 
    98     m_ViewFrustum.m_aPlanes[0].m_Norm.X = MatFinal._41-MatFinal._11;
    99     m_ViewFrustum.m_aPlanes[0].m_Norm.Y = MatFinal._42-MatFinal._12;
    100     m_ViewFrustum.m_aPlanes[0].m_Norm.Z = MatFinal._43-MatFinal._13;
    101     m_ViewFrustum.m_aPlanes[0].m_Dist   = MatFinal._44-MatFinal._14;
    102 
    103     //get the LEFT plane
    104     m_ViewFrustum.m_aPlanes[1].m_Norm.X = MatFinal._41+MatFinal._11;
    105     m_ViewFrustum.m_aPlanes[1].m_Norm.Y = MatFinal._42+MatFinal._12;
    106     m_ViewFrustum.m_aPlanes[1].m_Norm.Z = MatFinal._43+MatFinal._13;
    107     m_ViewFrustum.m_aPlanes[1].m_Dist   = MatFinal._44+MatFinal._14;
    108 
    109     //get the BOTTOM plane
    110     m_ViewFrustum.m_aPlanes[2].m_Norm.X = MatFinal._41+MatFinal._21;
    111     m_ViewFrustum.m_aPlanes[2].m_Norm.Y = MatFinal._42+MatFinal._22;
    112     m_ViewFrustum.m_aPlanes[2].m_Norm.Z = MatFinal._43+MatFinal._23;
    113     m_ViewFrustum.m_aPlanes[2].m_Dist   = MatFinal._44+MatFinal._24;
    114 
    115     //get the TOP plane
    116     m_ViewFrustum.m_aPlanes[3].m_Norm.X = MatFinal._41-MatFinal._21;
    117     m_ViewFrustum.m_aPlanes[3].m_Norm.Y = MatFinal._42-MatFinal._22;
    118     m_ViewFrustum.m_aPlanes[3].m_Norm.Z = MatFinal._43-MatFinal._23;
    119     m_ViewFrustum.m_aPlanes[3].m_Dist   = MatFinal._44-MatFinal._24;
    120 
    121     //get the FAR plane
    122     m_ViewFrustum.m_aPlanes[4].m_Norm.X = MatFinal._41-MatFinal._31;
    123     m_ViewFrustum.m_aPlanes[4].m_Norm.Y = MatFinal._42-MatFinal._32;
    124     m_ViewFrustum.m_aPlanes[4].m_Norm.Z = MatFinal._43-MatFinal._33;
    125     m_ViewFrustum.m_aPlanes[4].m_Dist   = MatFinal._44-MatFinal._34;
    126 
    127     //get the NEAR plane
    128     m_ViewFrustum.m_aPlanes[5].m_Norm.X = MatFinal._41+MatFinal._31;
    129     m_ViewFrustum.m_aPlanes[5].m_Norm.Y = MatFinal._42+MatFinal._32;
    130     m_ViewFrustum.m_aPlanes[5].m_Norm.Z = MatFinal._43+MatFinal._33;
    131     m_ViewFrustum.m_aPlanes[5].m_Dist   = MatFinal._44+MatFinal._34;
    132 }
    133 
    134 void CCamera::SetViewPort (const SViewPort& viewport)
     92    // get the RIGHT plane
     93    m_ViewFrustum.SetNumPlanes(6);
     94
     95    m_ViewFrustum.m_aPlanes[0].m_Norm.X = scissor[1].X*MatFinal._41 - MatFinal._11;
     96    m_ViewFrustum.m_aPlanes[0].m_Norm.Y = scissor[1].X*MatFinal._42 - MatFinal._12;
     97    m_ViewFrustum.m_aPlanes[0].m_Norm.Z = scissor[1].X*MatFinal._43 - MatFinal._13;
     98    m_ViewFrustum.m_aPlanes[0].m_Dist   = scissor[1].X*MatFinal._44 - MatFinal._14;
     99
     100    // get the LEFT plane
     101    m_ViewFrustum.m_aPlanes[1].m_Norm.X = -scissor[0].X*MatFinal._41 + MatFinal._11;
     102    m_ViewFrustum.m_aPlanes[1].m_Norm.Y = -scissor[0].X*MatFinal._42 + MatFinal._12;
     103    m_ViewFrustum.m_aPlanes[1].m_Norm.Z = -scissor[0].X*MatFinal._43 + MatFinal._13;
     104    m_ViewFrustum.m_aPlanes[1].m_Dist   = -scissor[0].X*MatFinal._44 + MatFinal._14;
     105
     106    // get the BOTTOM plane
     107    m_ViewFrustum.m_aPlanes[2].m_Norm.X = -scissor[0].Y*MatFinal._41 + MatFinal._21;
     108    m_ViewFrustum.m_aPlanes[2].m_Norm.Y = -scissor[0].Y*MatFinal._42 + MatFinal._22;
     109    m_ViewFrustum.m_aPlanes[2].m_Norm.Z = -scissor[0].Y*MatFinal._43 + MatFinal._23;
     110    m_ViewFrustum.m_aPlanes[2].m_Dist   = -scissor[0].Y*MatFinal._44 + MatFinal._24;
     111
     112    // get the TOP plane
     113    m_ViewFrustum.m_aPlanes[3].m_Norm.X = scissor[1].Y*MatFinal._41 - MatFinal._21;
     114    m_ViewFrustum.m_aPlanes[3].m_Norm.Y = scissor[1].Y*MatFinal._42 - MatFinal._22;
     115    m_ViewFrustum.m_aPlanes[3].m_Norm.Z = scissor[1].Y*MatFinal._43 - MatFinal._23;
     116    m_ViewFrustum.m_aPlanes[3].m_Dist   = scissor[1].Y*MatFinal._44 - MatFinal._24;
     117
     118    // get the FAR plane
     119    m_ViewFrustum.m_aPlanes[4].m_Norm.X = scissor[1].Z*MatFinal._41 - MatFinal._31;
     120    m_ViewFrustum.m_aPlanes[4].m_Norm.Y = scissor[1].Z*MatFinal._42 - MatFinal._32;
     121    m_ViewFrustum.m_aPlanes[4].m_Norm.Z = scissor[1].Z*MatFinal._43 - MatFinal._33;
     122    m_ViewFrustum.m_aPlanes[4].m_Dist   = scissor[1].Z*MatFinal._44 - MatFinal._34;
     123
     124    // get the NEAR plane
     125    m_ViewFrustum.m_aPlanes[5].m_Norm.X = -scissor[0].Z*MatFinal._41 + MatFinal._31;
     126    m_ViewFrustum.m_aPlanes[5].m_Norm.Y = -scissor[0].Z*MatFinal._42 + MatFinal._32;
     127    m_ViewFrustum.m_aPlanes[5].m_Norm.Z = -scissor[0].Z*MatFinal._43 + MatFinal._33;
     128    m_ViewFrustum.m_aPlanes[5].m_Dist   = -scissor[0].Z*MatFinal._44 + MatFinal._34;
     129}
     130
     131void CCamera::ClipFrustum(const CPlane& clipPlane)
     132{
     133    m_ViewFrustum.AddPlane(clipPlane);
     134}
     135
     136void CCamera::SetViewPort(const SViewPort& viewport)
    135137{
    136138    m_ViewPort.m_X = viewport.m_X;
  • ps/trunk/source/graphics/Camera.h

    r7930 r9814  
    2525
    2626#include "Frustum.h"
     27#include "maths/Bound.h"
    2728#include "maths/Matrix3D.h"
    2829
     
    3637};
    3738
    38 
    3939class CCamera
    4040{
    4141    public:
    42         CCamera ();
    43         ~CCamera ();
     42        CCamera();
     43        ~CCamera();
    4444       
    4545        // Methods for projection
    46         void SetProjection (float nearp, float farp, float fov);
    47         void SetProjectionTile (int tiles, int tile_x, int tile_y);
    48         CMatrix3D& GetProjection () { return m_ProjMat; }
    49         const CMatrix3D& GetProjection () const { return m_ProjMat; }
     46        void SetProjection(float nearp, float farp, float fov);
     47        void SetProjectionTile(int tiles, int tile_x, int tile_y);
     48        CMatrix3D& GetProjection() { return m_ProjMat; }
     49        const CMatrix3D& GetProjection() const { return m_ProjMat; }
     50
     51        CMatrix3D& GetOrientation() { return m_Orientation; }
     52        const CMatrix3D& GetOrientation() const { return m_Orientation; }
     53
     54        CMatrix3D GetViewProjection() { return m_ProjMat * m_Orientation.GetInverse(); }
    5055
    5156        // Updates the frustum planes. Should be called
    5257        // everytime the view or projection matrices are
    5358        // altered.
    54         void UpdateFrustum ();
    55         const CFrustum& GetFrustum () const { return m_ViewFrustum; }
     59        void UpdateFrustum(const CBound& scissor = CBound(CVector3D(-1.0f, -1.0f, -1.0f), CVector3D(1.0f, 1.0f, 1.0f)));
     60        void ClipFrustum(const CPlane& clipPlane);
     61        const CFrustum& GetFrustum() const { return m_ViewFrustum; }
    5662
    57         void SetViewPort (const SViewPort& viewport);
    58         const SViewPort& GetViewPort () const { return m_ViewPort; }
     63        void SetViewPort(const SViewPort& viewport);
     64        const SViewPort& GetViewPort() const { return m_ViewPort; }
    5965
    6066        // getters
  • ps/trunk/source/graphics/Frustum.cpp

    r6832 r9814  
    4848    if (m_NumPlanes >= MAX_NUM_FRUSTUM_PLANES)
    4949        m_NumPlanes = MAX_NUM_FRUSTUM_PLANES-1;
     50}
     51
     52void CFrustum::AddPlane (const CPlane& plane)
     53{
     54    if (m_NumPlanes >= MAX_NUM_FRUSTUM_PLANES)
     55    {
     56        debug_warn(L"CFrustum::AddPlane: Too many planes");
     57        return;
     58    }
     59
     60    m_aPlanes[m_NumPlanes++] = plane;
    5061}
    5162
  • ps/trunk/source/graphics/Frustum.h

    r6832 r9814  
    4949    size_t GetNumPlanes() const { return m_NumPlanes; }
    5050
     51    void AddPlane (const CPlane& plane);
     52
    5153    //The following methods return true if the shape is
    5254    //partially or completely in front of the frustum planes
  • ps/trunk/source/graphics/Model.cpp

    r9761 r9814  
    8282    if (numBones != 0)
    8383    {
     84        size_t numBlends = modeldef->GetNumBlends();
     85
    8486        // allocate matrices for bone transformations
    85         m_BoneMatrices = new CMatrix3D[numBones];
     87        m_BoneMatrices = new CMatrix3D[numBones + numBlends];
     88        for (size_t i = 0; i < numBones + numBlends; ++i)
     89        {
     90            m_BoneMatrices[i].SetIdentity();
     91        }
     92
    8693        m_InverseBindBoneMatrices = new CMatrix3D[numBones];
    8794
     
    9097        for (size_t i = 0; i < numBones; ++i)
    9198        {
    92             m_BoneMatrices[i].SetIdentity();
    93             m_BoneMatrices[i].Rotate(defpose[i].m_Rotation);
    94             m_BoneMatrices[i].Translate(defpose[i].m_Translation);
    95 
    9699            m_InverseBindBoneMatrices[i].SetIdentity();
    97100            m_InverseBindBoneMatrices[i].Translate(-defpose[i].m_Translation);
     
    101104
    102105    m_PositionValid = true;
    103    
     106
    104107    return true;
    105108}
     
    112115    // Need to calculate the object bounds first, if that hasn't already been done
    113116    if (! (m_Anim && m_Anim->m_AnimDef))
    114         CalcObjectBounds();
     117    {
     118        if (m_ObjectBounds.IsEmpty())
     119            CalcObjectBounds();
     120    }
    115121    else
    116122    {
     
    181187        for (size_t i=0;i<numverts;i++)
    182188        {
    183             result += CModelDef::SkinPoint(verts[i], GetAnimatedBoneMatrices(), GetInverseBindBoneMatrices());
     189            result += CModelDef::SkinPoint(verts[i], GetAnimatedBoneMatrices());
    184190        }
    185191        // advance to next frame
     
    323329        prop.m_Model->ValidatePosition();
    324330    }
     331
     332    if (m_BoneMatrices)
     333    {
     334        for (size_t i = 0; i < m_pModelDef->GetNumBones(); i++)
     335        {
     336            m_BoneMatrices[i] = m_BoneMatrices[i] * m_InverseBindBoneMatrices[i];
     337        }
     338
     339        m_pModelDef->BlendBoneMatrices(m_BoneMatrices);
     340    }
    325341}
    326342
  • ps/trunk/source/graphics/Model.h

    r9362 r9814  
    4141#define MODELFLAG_SILHOUETTE_DISPLAY    (1<<2)
    4242#define MODELFLAG_SILHOUETTE_OCCLUDER   (1<<3)
    43 
     43#define MODELFLAG_FILTERED          (1<<4)  // used internally by renderer
    4444
    4545///////////////////////////////////////////////////////////////////////////////
  • ps/trunk/source/graphics/ModelDef.cpp

    r8666 r9814  
    2828
    2929CVector3D CModelDef::SkinPoint(const SModelVertex& vtx,
    30                                const CMatrix3D newPoseMatrices[],
    31                                const CMatrix3D inverseBindMatrices[])
     30                               const CMatrix3D newPoseMatrices[])
    3231{
    3332    CVector3D result (0, 0, 0);
     
    3534    for (int i = 0; i < SVertexBlend::SIZE && vtx.m_Blend.m_Bone[i] != 0xff; ++i)
    3635    {
    37         CVector3D bindSpace = inverseBindMatrices[vtx.m_Blend.m_Bone[i]].Transform(vtx.m_Coords);
    38         CVector3D worldSpace = newPoseMatrices[vtx.m_Blend.m_Bone[i]].Transform(bindSpace);
    39         result += worldSpace * vtx.m_Blend.m_Weight[i];
     36        result += newPoseMatrices[vtx.m_Blend.m_Bone[i]].Transform(vtx.m_Coords) * vtx.m_Blend.m_Weight[i];
    4037    }
    4138
     
    4441
    4542CVector3D CModelDef::SkinNormal(const SModelVertex& vtx,
    46                                 const CMatrix3D newPoseMatrices[],
    47                                 const CMatrix3D inverseBindMatrices[])
     43                                const CMatrix3D newPoseMatrices[])
    4844{
    4945    // To be correct, the normal vectors apparently need to be multiplied by the
     
    7470    for (int i = 0; i < SVertexBlend::SIZE && vtx.m_Blend.m_Bone[i] != 0xff; ++i)
    7571    {
    76         CVector3D bindSpace = inverseBindMatrices[vtx.m_Blend.m_Bone[i]].Rotate(vtx.m_Norm);
    77         CVector3D worldSpace = newPoseMatrices[vtx.m_Blend.m_Bone[i]].Rotate(bindSpace);
    78         result += worldSpace * vtx.m_Blend.m_Weight[i];
     72        result += newPoseMatrices[vtx.m_Blend.m_Bone[i]].Rotate(vtx.m_Norm) * vtx.m_Blend.m_Weight[i];
    7973    }
    8074   
     
    9589        const VertexArrayIterator<CVector3D>& Normal,
    9690        const SModelVertex* vertices,
    97         const CMatrix3D newPoseMatrices[],
    98         const CMatrix3D inverseBindMatrices[])
     91        const size_t* blendIndices,
     92        const CMatrix3D newPoseMatrices[])
    9993{
    10094    for (size_t j = 0; j < numVertices; ++j)
    10195    {
    102         const SModelVertex vtx = vertices[j];
    103 
    104         CVector3D pos(0, 0, 0);
    105         CVector3D normal(0, 0, 0);
    106 
    107         for (int i = 0; i < SVertexBlend::SIZE && vtx.m_Blend.m_Bone[i] != 0xff; ++i)
    108         {
    109             CVector3D posBindSpace = inverseBindMatrices[vtx.m_Blend.m_Bone[i]].Transform(vtx.m_Coords);
    110             CVector3D normBindSpace = inverseBindMatrices[vtx.m_Blend.m_Bone[i]].Rotate(vtx.m_Norm);
    111 
    112             CVector3D posWorldSpace = newPoseMatrices[vtx.m_Blend.m_Bone[i]].Transform(posBindSpace);
    113             CVector3D normWorldSpace = newPoseMatrices[vtx.m_Blend.m_Bone[i]].Rotate(normBindSpace);
    114 
    115             pos += posWorldSpace * vtx.m_Blend.m_Weight[i];
    116             normal += normWorldSpace * vtx.m_Blend.m_Weight[i];
    117         }
     96        const SModelVertex& vtx = vertices[j];
     97
     98        Position[j] = newPoseMatrices[blendIndices[j]].Transform(vtx.m_Coords);
     99        Normal[j] = newPoseMatrices[blendIndices[j]].Rotate(vtx.m_Norm);
    118100
    119101        // If there was more than one influence, the result is probably not going
     
    123105        // optimise that case a bit.)
    124106        if (vtx.m_Blend.m_Bone[1] != 0xff) // if more than one influence
    125             normal.Normalize();
    126 
    127         Position[j] = pos;
    128         Normal[j] = normal;
     107            Normal[j].Normalize();
     108    }
     109}
     110
     111void CModelDef::BlendBoneMatrices(
     112        CMatrix3D boneMatrices[])
     113{
     114    for (size_t i = 0; i < m_NumBlends; ++i)
     115    {
     116        const SVertexBlend& blend = m_pBlends[i];
     117        CMatrix3D& boneMatrix = boneMatrices[m_NumBones + i];
     118        boneMatrix.Blend(boneMatrices[blend.m_Bone[0]], blend.m_Weight[0]);
     119        boneMatrix.AddBlend(boneMatrices[blend.m_Bone[1]], blend.m_Weight[1]);
     120        for (size_t j = 2; j < SVertexBlend::SIZE && blend.m_Bone[j] != 0xFF; ++j)
     121        {
     122            boneMatrix.AddBlend(boneMatrices[blend.m_Bone[j]], blend.m_Weight[j]);
     123        }
    129124    }
    130125}
    131126
    132127// CModelDef Constructor
    133 CModelDef::CModelDef() 
    134     : m_NumVertices(0), m_pVertices(0), m_NumFaces(0), m_pFaces(0), m_NumBones(0), m_Bones(0),
     128CModelDef::CModelDef() :
     129    m_NumVertices(0), m_pVertices(0), m_NumFaces(0), m_pFaces(0), m_NumBones(0), m_Bones(0),
     130    m_NumBlends(0), m_pBlends(0), m_pBlendIndices(0),
    135131    m_Name(L"[not loaded]")
    136132{
     
    145141    delete[] m_pFaces;
    146142    delete[] m_Bones;
     143    delete[] m_pBlends;
     144    delete[] m_pBlendIndices;
    147145}
    148146
     
    188186        mdef->m_Bones=new CBoneState[mdef->m_NumBones];
    189187        unpacker.UnpackRaw(mdef->m_Bones,mdef->m_NumBones*sizeof(CBoneState));
     188
     189        mdef->m_pBlendIndices = new size_t[mdef->m_NumVertices];
     190        std::vector<SVertexBlend> blends;
     191        for (size_t i = 0; i < mdef->m_NumVertices; i++)
     192        {
     193            const SVertexBlend &blend = mdef->m_pVertices[i].m_Blend;
     194            if (blend.m_Bone[1] == 0xFF)
     195            {
     196                mdef->m_pBlendIndices[i] = blend.m_Bone[0];
     197            }
     198            else
     199            {
     200                // If there's already a vertex using the same blend as this, then
     201                // reuse its entry from blends; otherwise add the new one to blends
     202                size_t j;
     203                for (j = 0; j < blends.size(); j++)
     204                {
     205                    if (blend == blends[j]) break;
     206                }
     207                if (j >= blends.size())
     208                    blends.push_back(blend);
     209                mdef->m_pBlendIndices[i] = mdef->m_NumBones + j;
     210            }
     211        }
     212
     213        mdef->m_NumBlends = blends.size();
     214        mdef->m_pBlends = new SVertexBlend[mdef->m_NumBlends];
     215        std::copy(blends.begin(), blends.end(), mdef->m_pBlends);
    190216    }
    191217
     
    233259        if (mdef->m_NumBones) // only do skinned models
    234260        {
    235             CMatrix3D identity;
    236             identity.SetIdentity();
    237             std::vector<CMatrix3D> identityBones (mdef->m_NumBones, identity);
    238 
    239261            std::vector<CMatrix3D> bindPose (mdef->m_NumBones);
    240262
     
    248270            for (size_t i = 0; i < mdef->m_NumVertices; ++i)
    249271            {
    250                 mdef->m_pVertices[i].m_Coords = SkinPoint(mdef->m_pVertices[i], &bindPose[0], &identityBones[0]);
    251                 mdef->m_pVertices[i].m_Norm = SkinNormal(mdef->m_pVertices[i], &bindPose[0], &identityBones[0]);
     272                mdef->m_pVertices[i].m_Coords = SkinPoint(mdef->m_pVertices[i], &bindPose[0]);
     273                mdef->m_pVertices[i].m_Norm = SkinNormal(mdef->m_pVertices[i], &bindPose[0]);
    252274            }
    253275        }
  • ps/trunk/source/graphics/ModelDef.h

    r8666 r9814  
    2929#include "renderer/VertexArray.h"
    3030#include <map>
     31#include <cstring>
    3132
    3233class CBoneState;
     
    5859    // weight of the influence; all weights sum to 1
    5960    float m_Weight[SIZE];
     61
     62    bool operator==(const SVertexBlend& o) const
     63    {
     64        return !memcmp(m_Bone, o.m_Bone, sizeof(m_Bone)) && !memcmp(m_Weight, o.m_Weight, sizeof(m_Weight));
     65    }
    6066};
    6167
     
    125131public:
    126132    // accessor: get vertex data
    127     size_t GetNumVertices() const { return (size_t)m_NumVertices; }
     133    size_t GetNumVertices() const { return m_NumVertices; }
    128134    SModelVertex* GetVertices() const { return m_pVertices; }
    129135
    130136    // accessor: get face data
    131     size_t GetNumFaces() const { return (size_t)m_NumFaces; }
     137    size_t GetNumFaces() const { return m_NumFaces; }
    132138    SModelFace* GetFaces() const { return m_pFaces; }
    133139
    134140    // accessor: get bone data
    135     size_t GetNumBones() const { return (size_t)m_NumBones; }
     141    size_t GetNumBones() const { return m_NumBones; }
    136142    CBoneState* GetBones() const { return m_Bones; }
     143
     144    // accessor: get blend data
     145    size_t GetNumBlends() const { return m_NumBlends; }
     146    SVertexBlend* GetBlends() const { return m_pBlends; }
     147    size_t* GetBlendIndices() const { return m_pBlendIndices; }
    137148
    138149    // find and return pointer to prop point matching given name; return
     
    146157     */
    147158    static CVector3D SkinPoint(const SModelVertex& vtx,
    148         const CMatrix3D newPoseMatrices[], const CMatrix3D inverseBindMatrices[]);
     159        const CMatrix3D newPoseMatrices[]);
    149160
    150161    /**
     
    154165     */
    155166    static CVector3D SkinNormal(const SModelVertex& vtx,
    156         const CMatrix3D newPoseMatrices[], const CMatrix3D inverseBindMatrices[]);
     167        const CMatrix3D newPoseMatrices[]);
    157168
    158169    /**
     
    166177        const VertexArrayIterator<CVector3D>& Normal,
    167178        const SModelVertex* vertices,
    168         const CMatrix3D newPoseMatrices[],
    169         const CMatrix3D inverseBindMatrices[]);
     179        const size_t* blendIndices,
     180        const CMatrix3D newPoseMatrices[]);
     181
     182    /**
     183     * Blend bone matrices together to fill bone palette.
     184     */
     185    void BlendBoneMatrices(CMatrix3D boneMatrices[]);
    170186
    171187    /**
     
    201217    size_t m_NumBones;
    202218    CBoneState* m_Bones;
     219    // blend data
     220    size_t m_NumBlends;
     221    SVertexBlend *m_pBlends;
     222    size_t* m_pBlendIndices;
    203223    // prop point data
    204224    std::vector<SPropPoint> m_PropPoints;
  • ps/trunk/source/graphics/ShaderTechnique.cpp

    r9362 r9814  
    2222CShaderPass::CShaderPass(const CShaderProgramPtr& shader) :
    2323    m_Shader(shader),
    24     m_HasAlpha(false), m_HasBlend(false), m_HasColorMask(false), m_HasDepthMask(false)
     24    m_HasAlpha(false), m_HasBlend(false), m_HasColorMask(false), m_HasDepthMask(false), m_HasDepthFunc(false)
    2525{
    2626}
     
    4747    if (m_HasDepthMask)
    4848        glDepthMask(m_DepthMask);
     49
     50    if (m_HasDepthFunc)
     51        glDepthFunc(m_DepthFunc);
    4952}
    5053
     
    6871    if (m_HasDepthMask)
    6972        glDepthMask(1);
     73
     74    if (m_HasDepthFunc)
     75        glDepthFunc(GL_LEQUAL);
    7076}
    7177
     
    97103    m_HasDepthMask = true;
    98104    m_DepthMask = mask;
     105}
     106
     107void CShaderPass::DepthFunc(GLenum func)
     108{
     109    m_HasDepthFunc = true;
     110    m_DepthFunc = func;
    99111}
    100112
  • ps/trunk/source/graphics/ShaderTechnique.h

    r9123 r9814  
    3434    void ColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a);
    3535    void DepthMask(GLboolean mask);
     36    void DepthFunc(GLenum func);
    3637
    3738    /**
     
    6667    bool m_HasDepthMask;
    6768    GLboolean m_DepthMask;
     69
     70    bool m_HasDepthFunc;
     71    GLenum m_DepthFunc;
    6872};
    6973
  • ps/trunk/source/maths/Bound.cpp

    r9362 r9814  
    3434
    3535///////////////////////////////////////////////////////////////////////////////
    36 // operator+=: extend this bound to include given bound
    37 CBound& CBound::operator+=(const CBound& b)
    38 {
    39 #define CMPT(c) \
    40     if (b[0].c < m_Data[0].c) m_Data[0].c = b[0].c; \
    41     if (b[1].c > m_Data[1].c) m_Data[1].c = b[1].c
    42     CMPT(X);
    43     CMPT(Y);
    44     CMPT(Z);
    45 #undef CMPT
    46 
    47     return *this;
    48 }
    49 
    50 ///////////////////////////////////////////////////////////////////////////////
    51 // operator+=: extend this bound to include given point
    52 CBound& CBound::operator+=(const CVector3D& pt)
    53 {
    54 #define CMPT(c) \
    55     if (pt.c < m_Data[0].c) m_Data[0].c = pt.c; \
    56     if (pt.c > m_Data[1].c) m_Data[1].c = pt.c
    57     CMPT(X);
    58     CMPT(Y);
    59     CMPT(Z);
    60 #undef CMPT
    61 
    62     return *this;
    63 }
    64 
    65 ///////////////////////////////////////////////////////////////////////////////
    6636// RayIntersect: intersect ray with this bound; return true
    6737// if ray hits (and store entry and exit times), or false
     
    157127///////////////////////////////////////////////////////////////////////////////
    158128// IsEmpty: tests whether this bound is empty
    159 bool CBound::IsEmpty()
     129bool CBound::IsEmpty() const
    160130{
    161131    return (m_Data[0].X ==  FLT_MAX && m_Data[0].Y ==  FLT_MAX && m_Data[0].Z ==  FLT_MAX
  • ps/trunk/source/maths/Bound.h

    r9345 r9814  
    4545
    4646    void SetEmpty();
    47     bool IsEmpty();
     47    bool IsEmpty() const;
    4848
    49     CBound& operator+=(const CBound& b);
    50     CBound& operator+=(const CVector3D& pt);
     49    void Extend(const CVector3D& min, const CVector3D& max)
     50    {
     51        if (min.X < m_Data[0].X) m_Data[0].X = min.X;
     52        if (min.Y < m_Data[0].Y) m_Data[0].Y = min.Y;
     53        if (min.Z < m_Data[0].Z) m_Data[0].Z = min.Z;
     54        if (max.X > m_Data[1].X) m_Data[1].X = max.X;
     55        if (max.Y > m_Data[1].Y) m_Data[1].Y = max.Y;
     56        if (max.Z > m_Data[1].Z) m_Data[1].Z = max.Z;
     57    }
     58
     59    // operator+=: extend this bound to include given bound
     60    CBound& operator+=(const CBound& b)
     61    {
     62        Extend(b.m_Data[0], b.m_Data[1]);
     63        return *this;
     64    }
     65
     66    // operator+=: extend this bound to include given point
     67    CBound& operator+=(const CVector3D& pt)
     68    {
     69        Extend(pt, pt);
     70        return *this;
     71    }
    5172
    5273    bool RayIntersect(const CVector3D& origin,const CVector3D& dir,float& tmin,float& tmax) const;
     
    5576    float GetVolume() const {
    5677        CVector3D v=m_Data[1]-m_Data[0];
    57         return v.X*v.Y*v.Z;
     78        return std::max(v.X, 0.0f)*std::max(v.Y, 0.0f)*std::max(v.Z, 0.0f);
    5879    }
    5980
  • ps/trunk/source/maths/MathUtil.h

    r7404 r9814  
    2424
    2525template <typename T>
    26 T Interpolate(const T& a, const T& b, float l)
     26inline T Interpolate(const T& a, const T& b, float l)
    2727{
    2828    return a + (b - a) * l;
  • ps/trunk/source/maths/Matrix3D.cpp

    r9298 r9814  
    2727#include "Vector4D.h"
    2828
    29 CMatrix3D::CMatrix3D ()
    30 {
    31 }
    32 
    33 CMatrix3D::CMatrix3D(
    34     float a11, float a12, float a13, float a14,
    35     float a21, float a22, float a23, float a24,
    36     float a31, float a32, float a33, float a34,
    37     float a41, float a42, float a43, float a44) :
    38     _11(a11), _12(a12), _13(a13), _14(a14),
    39     _21(a21), _22(a22), _23(a23), _24(a24),
    40     _31(a31), _32(a32), _33(a33), _34(a34),
    41     _41(a41), _42(a42), _43(a43), _44(a44)
    42 {
    43 }
    44 
    45 CMatrix3D::CMatrix3D(float data[])
    46 {
    47     for(int i=0; i<16; i++)
    48     {
    49         _data[i] = data[i];
    50     }
    51 }
    52 
    53 //Matrix multiplication
    54 CMatrix3D CMatrix3D::operator*(const CMatrix3D& matrix) const
    55 {
    56     return CMatrix3D(
    57         _11*matrix._11 + _12*matrix._21 + _13*matrix._31 + _14*matrix._41,
    58         _11*matrix._12 + _12*matrix._22 + _13*matrix._32 + _14*matrix._42,
    59         _11*matrix._13 + _12*matrix._23 + _13*matrix._33 + _14*matrix._43,
    60         _11*matrix._14 + _12*matrix._24 + _13*matrix._34 + _14*matrix._44,
    61 
    62         _21*matrix._11 + _22*matrix._21 + _23*matrix._31 + _24*matrix._41,
    63         _21*matrix._12 + _22*matrix._22 + _23*matrix._32 + _24*matrix._42,
    64         _21*matrix._13 + _22*matrix._23 + _23*matrix._33 + _24*matrix._43,
    65         _21*matrix._14 + _22*matrix._24 + _23*matrix._34 + _24*matrix._44,
    66 
    67         _31*matrix._11 + _32*matrix._21 + _33*matrix._31 + _34*matrix._41,
    68         _31*matrix._12 + _32*matrix._22 + _33*matrix._32 + _34*matrix._42,
    69         _31*matrix._13 + _32*matrix._23 + _33*matrix._33 + _34*matrix._43,
    70         _31*matrix._14 + _32*matrix._24 + _33*matrix._34 + _34*matrix._44,
    71 
    72         _41*matrix._11 + _42*matrix._21 + _43*matrix._31 + _44*matrix._41,
    73         _41*matrix._12 + _42*matrix._22 + _43*matrix._32 + _44*matrix._42,
    74         _41*matrix._13 + _42*matrix._23 + _43*matrix._33 + _44*matrix._43,
    75         _41*matrix._14 + _42*matrix._24 + _43*matrix._34 + _44*matrix._44
    76     );
    77 }
    78 
    79 //Matrix multiplication/assignment
    80 CMatrix3D& CMatrix3D::operator*=(const CMatrix3D& matrix)
    81 {
    82     Concatenate(matrix);   
    83     return *this;
    84 }
    85 
    86 //Matrix scaling
    87 CMatrix3D CMatrix3D::operator*(float f) const
    88 {
    89     CMatrix3D tmp;
    90     for (int i=0;i<16;i++) {
    91         tmp._data[i]=_data[i]*f;
    92     }
    93     return tmp;
    94 }
    95 
    96 //Matrix scaling/assignment
    97 CMatrix3D& CMatrix3D::operator*=(float f)
    98 {
    99     for (int i=0;i<16;i++) {
    100         _data[i]*=f;
    101     }
    102     return *this;
    103 }
    104 
    105 //Matrix addition
    106 CMatrix3D CMatrix3D::operator+(const CMatrix3D& m) const
    107 {
    108     CMatrix3D tmp;
    109     for (int i=0;i<16;i++) {
    110         tmp._data[i]=_data[i]+m._data[i];
    111     }
    112     return tmp;
    113 }
    114 
    115 //Matrix addition/assignment
    116 CMatrix3D& CMatrix3D::operator+=(const CMatrix3D& m)
    117 {
    118     for (int i=0;i<16;i++) {
    119         _data[i]+=m._data[i];
    120     }
    121     return *this;
    122 }
    123 
    124 bool CMatrix3D::operator==(const CMatrix3D &matrix) const
    125 {
    126     for (int i = 0; i < 16; ++i)
    127         if (matrix._data[i] != _data[i])
    128             return false;
    129     return true;
    130 }
    131 
    13229//Sets the identity matrix
    13330void CMatrix3D::SetIdentity ()
     
    274171    _24 += vector.Y;
    275172    _34 += vector.Z;
    276 }
    277 
    278 void CMatrix3D::Concatenate(const CMatrix3D& m)
    279 {
    280     (*this)=m*(*this);
    281173}
    282174
     
    342234{
    343235    return CVector3D(_13, _23, _33);
    344 }
    345 
    346 //Transform a vector by this matrix
    347 CVector4D CMatrix3D::Transform(const CVector4D &vector) const
    348 {
    349     CVector4D result;
    350     Transform(vector,result);
    351     return result;
    352 }
    353 
    354 void CMatrix3D::Transform(const CVector4D& vector,CVector4D& result) const
    355 {
    356     result[0] = _11*vector[0] + _12*vector[1] + _13*vector[2] + _14*vector[3];
    357     result[1] = _21*vector[0] + _22*vector[1] + _23*vector[2] + _24*vector[3];
    358     result[2] = _31*vector[0] + _32*vector[1] + _33*vector[2] + _34*vector[3];
    359     result[3] = _41*vector[0] + _42*vector[1] + _43*vector[2] + _44*vector[3];
    360236}
    361237
  • ps/trunk/source/maths/Matrix3D.h

    r9298 r9814  
    2525
    2626#include "maths/Vector3D.h"
    27 
    28 class CVector4D;
     27#include "maths/Vector4D.h"
     28
    2929class CQuaternion;
    3030
     
    5050public:
    5151    // constructors
    52     CMatrix3D();
    53     CMatrix3D(float a11,float a12,float a13,float a14,float a21,float a22,float a23,float a24,
    54         float a31,float a32,float a33,float a34,float a41,float a42,float a43,float a44);
    55     CMatrix3D(float data[]);
     52    CMatrix3D ()
     53    {
     54    }
     55
     56    CMatrix3D(
     57        float a11, float a12, float a13, float a14,
     58        float a21, float a22, float a23, float a24,
     59        float a31, float a32, float a33, float a34,
     60        float a41, float a42, float a43, float a44) :
     61        _11(a11), _12(a12), _13(a13), _14(a14),
     62        _21(a21), _22(a22), _23(a23), _24(a24),
     63        _31(a31), _32(a32), _33(a33), _34(a34),
     64        _41(a41), _42(a42), _43(a43), _44(a44)
     65    {
     66    }
     67
     68    CMatrix3D(float data[]) :
     69        _11(data[0]), _21(data[1]), _31(data[2]), _41(data[3]),
     70        _12(data[4]), _22(data[5]), _32(data[6]), _42(data[7]),
     71        _13(data[8]), _23(data[9]), _33(data[10]), _43(data[11]),
     72        _14(data[12]), _24(data[13]), _34(data[14]), _44(data[15])
     73    {
     74    }
    5675
    5776    // accessors to individual elements of matrix
     
    6483
    6584    // matrix multiplication
    66     CMatrix3D operator*(const CMatrix3D &matrix) const;
     85    CMatrix3D operator*(const CMatrix3D &matrix) const
     86    {
     87        return CMatrix3D(
     88            _11*matrix._11 + _12*matrix._21 + _13*matrix._31 + _14*matrix._41,
     89            _11*matrix._12 + _12*matrix._22 + _13*matrix._32 + _14*matrix._42,
     90            _11*matrix._13 + _12*matrix._23 + _13*matrix._33 + _14*matrix._43,
     91            _11*matrix._14 + _12*matrix._24 + _13*matrix._34 + _14*matrix._44,
     92
     93            _21*matrix._11 + _22*matrix._21 + _23*matrix._31 + _24*matrix._41,
     94            _21*matrix._12 + _22*matrix._22 + _23*matrix._32 + _24*matrix._42,
     95            _21*matrix._13 + _22*matrix._23 + _23*matrix._33 + _24*matrix._43,
     96            _21*matrix._14 + _22*matrix._24 + _23*matrix._34 + _24*matrix._44,
     97
     98            _31*matrix._11 + _32*matrix._21 + _33*matrix._31 + _34*matrix._41,
     99            _31*matrix._12 + _32*matrix._22 + _33*matrix._32 + _34*matrix._42,
     100            _31*matrix._13 + _32*matrix._23 + _33*matrix._33 + _34*matrix._43,
     101            _31*matrix._14 + _32*matrix._24 + _33*matrix._34 + _34*matrix._44,
     102
     103            _41*matrix._11 + _42*matrix._21 + _43*matrix._31 + _44*matrix._41,
     104            _41*matrix._12 + _42*matrix._22 + _43*matrix._32 + _44*matrix._42,
     105            _41*matrix._13 + _42*matrix._23 + _43*matrix._33 + _44*matrix._43,
     106            _41*matrix._14 + _42*matrix._24 + _43*matrix._34 + _44*matrix._44
     107        );
     108    }
     109
    67110    // matrix multiplication/assignment
    68     CMatrix3D& operator*=(const CMatrix3D &matrix);
     111    CMatrix3D& operator*=(const CMatrix3D &matrix)
     112    {
     113        Concatenate(matrix);
     114        return *this;
     115    }
     116
    69117    // matrix scaling
    70     CMatrix3D operator*(float f) const;
    71     // matrix scaling/assignment
    72     CMatrix3D& operator*=(float f);
     118    CMatrix3D operator*(float f) const
     119    {
     120        return CMatrix3D(
     121            _11*f, _12*f, _13*f, _14*f,
     122            _21*f, _22*f, _23*f, _24*f,
     123            _31*f, _32*f, _33*f, _34*f,
     124            _41*f, _42*f, _43*f, _44*f
     125        );
     126    }
     127
    73128    // matrix addition
    74     CMatrix3D operator+(const CMatrix3D &matrix) const;
     129    CMatrix3D operator+(const CMatrix3D &m) const
     130    {
     131        return CMatrix3D(
     132            _11+m._11, _12+m._12, _13+m._13, _14+m._14,
     133            _21+m._21, _22+m._22, _23+m._23, _24+m._24,
     134            _31+m._31, _32+m._32, _33+m._33, _34+m._34,
     135            _41+m._41, _42+m._42, _43+m._43, _44+m._44
     136        );
     137    }
     138
    75139    // matrix addition/assignment
    76     CMatrix3D& operator+=(const CMatrix3D &matrix);
     140    CMatrix3D& operator+=(const CMatrix3D &m)
     141    {
     142        _11 += m._11; _21 += m._21; _31 += m._31; _41 += m._41;
     143        _12 += m._12; _22 += m._22; _32 += m._32; _42 += m._42;
     144        _13 += m._13; _23 += m._23; _33 += m._33; _43 += m._43;
     145        _14 += m._14; _24 += m._24; _34 += m._34; _44 += m._44;
     146        return *this;
     147    }
    77148
    78149    // equality
    79     bool operator==(const CMatrix3D &matrix) const;
     150    bool operator==(const CMatrix3D &m) const
     151    {
     152        return _11 == m._11 && _21 == m._21 && _31 == m._31 && _41 == m._41 &&
     153                 _12 == m._12 && _22 == m._22 && _32 == m._32 && _42 == m._42 &&
     154                 _13 == m._13 && _23 == m._23 && _33 == m._33 && _43 == m._43 &&
     155                 _14 == m._14 && _24 == m._24 && _34 == m._34 && _44 == m._44;
     156    }
    80157
    81158    // set this matrix to the identity matrix
     
    85162
    86163    // concatenate arbitrary matrix onto this matrix
    87     void Concatenate(const CMatrix3D& m);
     164    void Concatenate(const CMatrix3D& m)
     165    {
     166        (*this) = m * (*this);
     167    }
     168
     169    // blend matrix using only 4x3 subset
     170    void Blend(const CMatrix3D& m, float f)
     171    {
     172        _11 = m._11*f; _21 = m._21*f; _31 = m._31*f;
     173        _12 = m._12*f; _22 = m._22*f; _32 = m._32*f;
     174        _13 = m._13*f; _23 = m._23*f; _33 = m._33*f;
     175        _14 = m._14*f; _24 = m._24*f; _34 = m._34*f;
     176    }
     177
     178    // blend matrix using only 4x3 and add onto existing blend
     179    void AddBlend(const CMatrix3D& m, float f)
     180    {
     181        _11 += m._11*f; _21 += m._21*f; _31 += m._31*f;
     182        _12 += m._12*f; _22 += m._22*f; _32 += m._32*f;
     183        _13 += m._13*f; _23 += m._23*f; _33 += m._33*f;
     184        _14 += m._14*f; _24 += m._24*f; _34 += m._34*f;
     185    }
    88186
    89187    // set this matrix to a rotation matrix for a rotation about X axis of given angle
     
    145243
    146244    // transform a 3D vector by this matrix
    147     CVector3D Transform (const CVector3D &vector) const
     245    CVector3D Transform(const CVector3D &vector) const
    148246    {
    149247        CVector3D result;
     
    159257    }
    160258
     259    // transform a 4D vector by this matrix
     260    CVector4D Transform(const CVector4D &vector) const
     261    {
     262        CVector4D result;
     263        Transform(vector, result);
     264        return result;
     265    }
     266
     267    void Transform(const CVector4D& vector, CVector4D& result) const
     268    {
     269        result[0] = _11*vector[0] + _12*vector[1] + _13*vector[2] + _14*vector[3];
     270        result[1] = _21*vector[0] + _22*vector[1] + _23*vector[2] + _24*vector[3];
     271        result[2] = _31*vector[0] + _32*vector[1] + _33*vector[2] + _34*vector[3];
     272        result[3] = _41*vector[0] + _42*vector[1] + _43*vector[2] + _44*vector[3];
     273    }
     274
    161275    // rotate a vector by this matrix
    162276    CVector3D Rotate(const CVector3D& vector) const
     
    173287        result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z;
    174288    }
    175 
    176     // transform a 4D vector by this matrix
    177     void Transform(const CVector4D& vector,CVector4D& result) const;
    178     CVector4D Transform(const CVector4D& vector) const;
    179289
    180290    // rotate a vector by the transpose of this matrix
  • ps/trunk/source/maths/Plane.h

    r7805 r9814  
    2727
    2828#include "Vector3D.h"
     29#include "Vector4D.h"
    2930
    3031enum PLANESIDE
     
    3940    public:
    4041        CPlane ();
     42        CPlane (const CVector4D& coeffs) : m_Norm(coeffs[0], coeffs[1], coeffs[2]), m_Dist(coeffs[3]) { }
    4143
    4244        //sets the plane equation from 3 points on that plane
  • ps/trunk/source/ps/GameSetup/Config.cpp

    r9410 r9814  
    3535
    3636bool g_Shadows = false;
     37bool g_ShadowPCF = false;
    3738bool g_FancyWater = false;
    3839
     
    7374    CFG_GET_USER_VAL("novbo", Bool, g_NoGLVBO);
    7475    CFG_GET_USER_VAL("shadows", Bool, g_Shadows);
     76    CFG_GET_USER_VAL("shadowpcf", Bool, g_ShadowPCF);
    7577    CFG_GET_USER_VAL("fancywater", Bool, g_FancyWater);
    7678    CFG_GET_USER_VAL("renderpath", String, g_RenderPath);
  • ps/trunk/source/ps/GameSetup/Config.h

    r9189 r9814  
    4646// flag to switch on reflective/refractive water
    4747extern bool g_FancyWater;
     48// flag to switch on shadow PCF
     49extern bool g_ShadowPCF;
    4850
    4951extern float g_LodBias;
  • ps/trunk/source/ps/GameSetup/GameSetup.cpp

    r9768 r9814  
    550550    g_Renderer.SetRenderPath(CRenderer::GetRenderPathByName(g_RenderPath));
    551551    g_Renderer.SetOptionFloat(CRenderer::OPT_LODBIAS, g_LodBias);
     552    g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWPCF, g_ShadowPCF);
    552553
    553554    // create terrain related stuff
  • ps/trunk/source/ps/GameSetup/HWDetect.cpp

    r9556 r9814  
    116116}
    117117
     118void SetDisableShadowPCF(void* UNUSED(cbdata), bool disabled)
     119{
     120    if (!IsOverridden("shadowpcf"))
     121        g_ShadowPCF = !disabled;
     122}
     123
    118124void SetDisableFancyWater(void* UNUSED(cbdata), bool disabled)
    119125{
     
    137143    scriptInterface.RegisterFunction<void, bool, &SetDisableS3TC>("SetDisableS3TC");
    138144    scriptInterface.RegisterFunction<void, bool, &SetDisableShadows>("SetDisableShadows");
     145    scriptInterface.RegisterFunction<void, bool, &SetDisableShadowPCF>("SetDisableShadowPCF");
    139146    scriptInterface.RegisterFunction<void, bool, &SetDisableFancyWater>("SetDisableFancyWater");
    140147    scriptInterface.RegisterFunction<void, std::string, &SetRenderPath>("SetRenderPath");
  • ps/trunk/source/renderer/DecalRData.h

    r9142 r9814  
    3535    void Render(const CShaderProgramPtr& shader);
    3636
     37    CModelDecal* GetDecal() { return m_Decal; }
     38
    3739private:
    3840    void BuildArrays();
  • ps/trunk/source/renderer/ModelRenderer.cpp

    r9362 r9814  
    8585        }
    8686
    87         CModelDef::SkinPointsAndNormals(numVertices, Position, Normal, vertices, model->GetAnimatedBoneMatrices(), model->GetInverseBindBoneMatrices());
     87        CModelDef::SkinPointsAndNormals(numVertices, Position, Normal, vertices, mdef->GetBlendIndices(), model->GetAnimatedBoneMatrices());
    8888
    8989    }
     
    254254
    255255    void RenderAllModels(const RenderModifierPtr& modifier, int filterflags, int pass, int streamflags);
     256    void FilterAllModels(CModelFilter& filter, int passed, int filterflags);
    256257};
    257258
     
    443444                ENSURE(bmrdata->GetKey() == this);
    444445
    445                 if (filterflags && !(model->GetFlags()&filterflags))
     446                if (filterflags && !(model->GetFlags() & filterflags))
    446447                    continue;
    447448
     
    453454}
    454455
    455 
     456void BatchModelRenderer::Filter(CModelFilter& filter, int passed, int flags)
     457{
     458    if (!HaveSubmissions())
     459        return;
     460
     461    m->FilterAllModels(filter, passed, flags);
     462}
     463
     464// Recompute filter flags
     465void BatchModelRendererInternals::FilterAllModels(CModelFilter& filter, int passed, int filterflags)
     466{
     467    for(BMRModelDefTracker* mdeftracker = submissions; mdeftracker; mdeftracker = mdeftracker->m_Next)
     468    {
     469        for(size_t idx = 0; idx < mdeftracker->m_Slots; ++idx)
     470        {
     471            BMRModelData* bmrdata = mdeftracker->m_ModelSlots[idx];
     472            for(; bmrdata; bmrdata = bmrdata->m_Next)
     473            {
     474                CModel* model = bmrdata->GetModel();
     475                if (filterflags && !(model->GetFlags() & filterflags))
     476                    continue;
     477
     478                if (filter.Filter(model))
     479                    model->SetFlags(model->GetFlags() | passed);
     480                else
     481                    model->SetFlags(model->GetFlags() & ~passed);
     482            }
     483        }
     484    }
     485}
  • ps/trunk/source/renderer/ModelRenderer.h

    r9187 r9814  
    4343class CModel;
    4444
     45class CModelFilter
     46{
     47public:
     48    virtual ~CModelFilter() {}
     49    virtual bool Filter(CModel* model) = 0;
     50};
    4551
    4652/**
     
    168174     */
    169175    virtual void Render(const RenderModifierPtr& modifier, int flags) = 0;
     176
     177    /**
     178     * Filter: Filter submitted models, setting the passed flags on any models
     179     * that pass the filter, and clearing them from models that fail.
     180     *
     181     * @param filter Filter to select a subset of models.
     182     * @param passed Flags to be set/cleared.
     183     * @param flags If non-zero, only models that contain @p flags
     184     * have the filter test applied.
     185     */
     186    virtual void Filter(CModelFilter& filter, int passed, int flags = 0) = 0;
    170187
    171188    /**
     
    269286    virtual bool HaveSubmissions();
    270287    virtual void Render(const RenderModifierPtr& modifier, int flags);
     288    virtual void Filter(CModelFilter& filter, int passed, int flags);
    271289
    272290private:
  • ps/trunk/source/renderer/PatchRData.cpp

    r9635 r9814  
    5858// CPatchRData constructor
    5959CPatchRData::CPatchRData(CPatch* patch) :
    60     m_Patch(patch), m_VBSides(0), m_VBBase(0), m_VBBaseIndices(0), m_VBBlends(0), m_VBBlendIndices(0)
     60    m_Patch(patch), m_VBSides(0),
     61    m_VBBase(0), m_VBBaseIndices(0),
     62    m_VBBlends(0), m_VBBlendIndices(0),
     63    m_VBWater(0), m_VBWaterIndices(0)
    6164{
    6265    ENSURE(patch);
     
    7477    if (m_VBBlends) g_VBMan.Release(m_VBBlends);
    7578    if (m_VBBlendIndices) g_VBMan.Release(m_VBBlendIndices);
     79    if (m_VBWater) g_VBMan.Release(m_VBWater);
     80    if (m_VBWaterIndices) g_VBMan.Release(m_VBWaterIndices);
    7681}
    7782
     
    646651    BuildIndices();
    647652    BuildBlends();
     653    BuildWater();
    648654}
    649655
     
    658664        BuildIndices();
    659665        BuildBlends();
     666        BuildWater();
    660667
    661668        m_UpdateFlags=0;
     
    11281135    }
    11291136}
     1137
     1138//
     1139// Water build and rendering
     1140//
     1141
     1142// Build vertex buffer for water vertices over our patch
     1143void CPatchRData::BuildWater()
     1144{
     1145    // number of vertices in each direction in each patch
     1146    ENSURE((PATCH_SIZE % water_cell_size) == 0);
     1147
     1148    if (m_VBWater)
     1149    {
     1150        g_VBMan.Release(m_VBWater);
     1151        m_VBWater = 0;
     1152    }
     1153    if (m_VBWaterIndices)
     1154    {
     1155        g_VBMan.Release(m_VBWaterIndices);
     1156        m_VBWaterIndices = 0;
     1157    }
     1158    m_WaterBounds.SetEmpty();
     1159
     1160    // We need to use this to access the water manager or we may not have the
     1161    // actual values but some compiled-in defaults
     1162    CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     1163    if (cmpWaterManager.null())
     1164        return;
     1165
     1166    // Build data for water
     1167    std::vector<SWaterVertex> water_vertex_data;
     1168    std::vector<GLushort> water_indices;
     1169    u16 water_index_map[PATCH_SIZE+1][PATCH_SIZE+1];
     1170    memset(water_index_map, 0xFF, sizeof(water_index_map));
     1171
     1172    // TODO: This is not (yet) exported via the ICmp interface so... we stick to these values which can be compiled in defaults
     1173    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     1174
     1175    CPatch* patch = m_Patch;
     1176    CTerrain* terrain = patch->m_Parent;
     1177
     1178    ssize_t x1 = m_Patch->m_X*PATCH_SIZE;
     1179    ssize_t z1 = m_Patch->m_Z*PATCH_SIZE;
     1180
     1181    // build vertices, uv, and shader varying
     1182    for (ssize_t z = 0; z < PATCH_SIZE; z += water_cell_size)
     1183    {
     1184        for (ssize_t x = 0; x <= PATCH_SIZE; x += water_cell_size)
     1185        {
     1186            // Check that the edge at x is partially underwater
     1187            float startTerrainHeight[2] = { terrain->GetVertexGroundLevel(x+x1, z+z1), terrain->GetVertexGroundLevel(x+x1, z+z1 + water_cell_size) };
     1188            float startWaterHeight[2] = { cmpWaterManager->GetExactWaterLevel(x+x1, z+z1), cmpWaterManager->GetExactWaterLevel(x+x1, z+z1 + water_cell_size) };
     1189            if (startTerrainHeight[0] >= startWaterHeight[0] && startTerrainHeight[1] >= startWaterHeight[1])
     1190                continue;
     1191
     1192            // Move x back one cell (unless at start of patch), then scan rightwards
     1193            bool belowWater = true;
     1194            ssize_t stripStart;
     1195            for (stripStart = x = std::max(x-water_cell_size, (ssize_t)0); x <= PATCH_SIZE; x += water_cell_size)
     1196            {
     1197                // If this edge is not underwater, and neither is the previous edge
     1198                // (i.e. belowWater == false), then stop this strip since we've reached
     1199                // a cell that's entirely above water
     1200                float terrainHeight[2] = { terrain->GetVertexGroundLevel(x+x1, z+z1), terrain->GetVertexGroundLevel(x+x1, z+z1 + water_cell_size) };
     1201                float waterHeight[2] = { cmpWaterManager->GetExactWaterLevel(x+x1, z+z1), cmpWaterManager->GetExactWaterLevel(x+x1, z+z1 + water_cell_size) };
     1202                if (terrainHeight[0] >= waterHeight[0] && terrainHeight[1] >= waterHeight[1])
     1203                {
     1204                    if (!belowWater)
     1205                        break;
     1206                    belowWater = false;
     1207                }
     1208                else
     1209                    belowWater = true;
     1210
     1211                // Edge (x,z)-(x,z+1) is at least partially underwater, so extend the water plane strip across it
     1212
     1213                // Compute vertex data for the 2 points on the edge
     1214                for (int j = 0; j < 2; j++)
     1215                {
     1216                    // Check if we already computed this vertex from an earlier strip
     1217                    if (water_index_map[z+j*water_cell_size][x] != 0xFFFF)
     1218                        continue;
     1219
     1220                    SWaterVertex vertex;
     1221
     1222                    terrain->CalcPosition(x+x1, z+z1 + j*water_cell_size, vertex.m_Position);
     1223                    float depth = waterHeight[j] - vertex.m_Position.Y;
     1224                    vertex.m_Position.Y = waterHeight[j];
     1225                    m_WaterBounds += vertex.m_Position;
     1226
     1227                    // NB: Usually this factor is view dependent, but for performance reasons
     1228                    // we do not take it into account with basic non-shader based water.
     1229                    // Average constant Fresnel effect for non-fancy water
     1230                    float alpha = clamp(depth / WaterMgr->m_WaterFullDepth + WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha);
     1231
     1232                    // Split the depth data across 24 bits, so the fancy-water shader can reconstruct
     1233                    // the depth value while the simple-water can just use the precomputed alpha
     1234                    float depthInt = floor(depth);
     1235                    float depthFrac = depth - depthInt;
     1236                    vertex.m_DepthData = SColor4ub(
     1237                        u8(clamp(depthInt, 0.0f, 255.0f)),
     1238                        u8(clamp(-depthInt, 0.0f, 255.0f)),
     1239                        u8(clamp(depthFrac*255.0f, 0.0f, 255.0f)),
     1240                        u8(clamp(alpha*255.0f, 0.0f, 255.0f)));
     1241
     1242                    water_index_map[z+j*water_cell_size][x] = water_vertex_data.size();
     1243                    water_vertex_data.push_back(vertex);
     1244                }
     1245
     1246                // If this was not the first x in the strip, then add a quad
     1247                // using the computed vertex data
     1248
     1249                if (x <= stripStart)
     1250                    continue;
     1251
     1252                water_indices.push_back(water_index_map[z + water_cell_size][x - water_cell_size]);
     1253                water_indices.push_back(water_index_map[z][x - water_cell_size]);
     1254                water_indices.push_back(water_index_map[z][x]);
     1255                water_indices.push_back(water_index_map[z + water_cell_size][x]);
     1256            }
     1257        }
     1258    }
     1259
     1260    // no vertex buffers if no data generated
     1261    if (water_indices.size() == 0)
     1262        return;
     1263
     1264    // allocate vertex buffer
     1265    m_VBWater = g_VBMan.Allocate(sizeof(SWaterVertex), water_vertex_data.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER);
     1266    m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater, &water_vertex_data[0]);
     1267
     1268    // Construct indices buffer
     1269    m_VBWaterIndices = g_VBMan.Allocate(sizeof(GLushort), water_indices.size(), GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER);
     1270    m_VBWaterIndices->m_Owner->UpdateChunkVertices(m_VBWaterIndices, &water_indices[0]);
     1271}
     1272
     1273void CPatchRData::RenderWater()
     1274{
     1275    ASSERT(m_UpdateFlags==0);
     1276
     1277    if (!m_VBWater)
     1278        return;
     1279
     1280    SWaterVertex *base=(SWaterVertex *)m_VBWater->m_Owner->Bind();
     1281
     1282    // setup data pointers
     1283    GLsizei stride = sizeof(SWaterVertex);
     1284    glColorPointer(4, GL_UNSIGNED_BYTE, stride, &base[m_VBWater->m_Index].m_DepthData);
     1285    glVertexPointer(3, GL_FLOAT, stride, &base[m_VBWater->m_Index].m_Position);
     1286
     1287    // render
     1288    if (!g_Renderer.m_SkipSubmit) {
     1289        u8* indexBase = m_VBWaterIndices->m_Owner->Bind();
     1290        glDrawElements(GL_QUADS, (GLsizei) m_VBWaterIndices->m_Count,
     1291            GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(m_VBWaterIndices->m_Index));
     1292    }
     1293
     1294    // bump stats
     1295    g_Renderer.m_Stats.m_DrawCalls++;
     1296    g_Renderer.m_Stats.m_WaterTris += m_VBWaterIndices->m_Count / 2;
     1297
     1298    CVertexBuffer::Unbind();
     1299}
  • ps/trunk/source/renderer/PatchRData.h

    r9132 r9814  
    4242    void RenderPriorities();
    4343
     44    void RenderWater();
     45
    4446    static void RenderBases(const std::vector<CPatchRData*>& patches);
    4547    static void RenderBlends(const std::vector<CPatchRData*>& patches);
     
    4749
    4850    CPatch* GetPatch() { return m_Patch; }
     51
     52    const CBound& GetWaterBounds() const { return m_WaterBounds; }
    4953
    5054private:
     
    9498    cassert(sizeof(SBlendVertex) == 32);
    9599
     100    // Mixed Fancy/Simple water vertex description data structure
     101    struct SWaterVertex {
     102        // vertex position
     103        CVector3D m_Position;
     104        // (p,q,r, a) where
     105        //   p*255 + q*-255 + r = depth of water
     106        //   a = depth-dependent alpha
     107        SColor4ub m_DepthData;
     108    };
     109    cassert(sizeof(SWaterVertex) == 16);
     110
    96111    // build this renderdata object
    97112    void Build();
     
    129144    // splats used in blend pass
    130145    std::vector<SSplat> m_BlendSplats;
     146
     147    // boundary of water in this patch
     148    CBound m_WaterBounds;
     149
     150    // Water vertex buffer
     151    CVertexBuffer::VBChunk* m_VBWater;
     152
     153    // Water indices buffer
     154    CVertexBuffer::VBChunk* m_VBWaterIndices;
     155
     156    // Build water vertices and indices (vertex buffer and data vector)
     157    void BuildWater();
     158
     159    // parameter allowing a varying number of triangles per patch for LOD
     160    // MUST be an exact divisor of PATCH_SIZE
     161    // compiled const for the moment until/if dynamic water LOD is offered
     162    // savings would be mostly beneficial for GPU or simple water
     163    static const ssize_t water_cell_size = 1;
    131164};
    132165
  • ps/trunk/source/renderer/RenderModifiers.cpp

    r9362 r9814  
    237237        shader->BindTexture("shadowTex", GetShadowMap()->GetTexture());
    238238        shader->Uniform("shadowTransform", GetShadowMap()->GetTextureMatrix());
     239
     240        const float* offsets = GetShadowMap()->GetFilterOffsets();
     241        shader->Uniform("shadowOffsets1", offsets[0], offsets[1], offsets[2], offsets[3]);
     242        shader->Uniform("shadowOffsets2", offsets[4], offsets[5], offsets[6], offsets[7]);
    239243    }
    240244
  • ps/trunk/source/renderer/Renderer.cpp

    r9410 r9814  
    105105        Row_DrawCalls = 0,
    106106        Row_TerrainTris,
     107        Row_WaterTris,
    107108        Row_ModelTris,
    108109        Row_BlendSplats,
     
    161162            return "# terrain tris";
    162163        sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_TerrainTris);
     164        return buf;
     165
     166    case Row_WaterTris:
     167        if (col == 0)
     168            return "# water tris";
     169        sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_WaterTris);
    163170        return buf;
    164171
     
    296303        RenderModifierPtr ModSolidPlayerInstancing;
    297304        RenderModifierPtr ModTransparent;
     305        RenderModifierPtr ModTransparentOpaque;
     306        RenderModifierPtr ModTransparentBlend;
    298307
    299308        // Palette of available RenderModifiers
     
    301310        RenderModifierPtr ModPlayerUnlit;
    302311        RenderModifierPtr ModTransparentUnlit;
     312        RenderModifierPtr ModTransparentOpaqueUnlit;
     313        RenderModifierPtr ModTransparentBlendUnlit;
    303314
    304315        RenderModifierPtr ModShaderSolidColor;
     
    312323        LitRenderModifierPtr ModShaderPlayerInstancing;
    313324        LitRenderModifierPtr ModShaderTransparent;
     325        LitRenderModifierPtr ModShaderTransparentOpaque;
     326        LitRenderModifierPtr ModShaderTransparentBlend;
    314327        RenderModifierPtr ModShaderTransparentShadow;
    315328    } Model;
     
    382395            Model.PlayerInstancing->Render(modPlayerInstancing, flags);
    383396    }
     397
     398    /**
     399     * Filters all non-transparent models with the given modifiers.
     400     */
     401    void FilterModels(CModelFilter& filter, int passed, int flags = 0)
     402    {
     403        Model.Normal->Filter(filter, passed, flags);
     404        if (Model.Normal != Model.NormalInstancing)
     405            Model.NormalInstancing->Filter(filter, passed, flags);
     406
     407        Model.Player->Filter(filter, passed, flags);
     408        if (Model.Player != Model.PlayerInstancing)
     409            Model.PlayerInstancing->Filter(filter, passed, flags);
     410    }
    384411};
    385412
     
    413440    m_Options.m_ShadowAlphaFix = true;
    414441    m_Options.m_ARBProgramShadow = true;
     442    m_Options.m_ShadowPCF = false;
    415443
    416444    m_ShadowZBias = 0.02f;
     
    515543        if (m_Caps.m_ARBProgramShadow && m_Options.m_ARBProgramShadow)
    516544            defBasic["USE_FP_SHADOW"] = "1";
     545        if (m_Options.m_ShadowPCF)
     546            defBasic["USE_SHADOW_PCF"] = "1";
    517547    }
    518548
     
    527557
    528558    // TODO: it'd be nicer to load this technique from an XML file or something
    529     CShaderPass passTransparent0(m->shaderManager.LoadProgram("solid_tex", defNull));
    530     passTransparent0.AlphaFunc(GL_GREATER, 0.975f);
    531     passTransparent0.ColorMask(0, 0, 0, 0);
    532     CShaderPass passTransparent1(m->shaderManager.LoadProgram("model_common", defTransparent));
    533     passTransparent1.AlphaFunc(GL_GREATER, 0.0f);
    534     passTransparent1.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    535     passTransparent1.DepthMask(0);
    536     CShaderTechnique techTransparent(passTransparent0);
    537     techTransparent.AddPass(passTransparent1);
     559    CShaderPass passTransparentOpaque(m->shaderManager.LoadProgram("model_common", defTransparent));
     560    passTransparentOpaque.AlphaFunc(GL_GREATER, 0.9375f);
     561    passTransparentOpaque.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     562    CShaderTechnique techTransparentOpaque(passTransparentOpaque);
     563
     564    CShaderPass passTransparentBlend(m->shaderManager.LoadProgram("model_common", defTransparent));
     565    passTransparentBlend.AlphaFunc(GL_GREATER, 0.0f);
     566    passTransparentBlend.DepthFunc(GL_LESS);
     567    passTransparentBlend.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     568    passTransparentBlend.DepthMask(0);
     569    CShaderTechnique techTransparentBlend(passTransparentBlend);
     570
     571    CShaderTechnique techTransparent(passTransparentOpaque);
     572    techTransparent.AddPass(passTransparentBlend);
    538573
    539574    CShaderPass passTransparentShadow(m->shaderManager.LoadProgram("solid_tex", defBasic));
     
    566601    m->Model.ModShaderTransparent = LitRenderModifierPtr(new ShaderRenderModifier(
    567602            techTransparent));
     603    m->Model.ModShaderTransparentOpaque = LitRenderModifierPtr(new ShaderRenderModifier(
     604            techTransparentOpaque));
     605    m->Model.ModShaderTransparentBlend = LitRenderModifierPtr(new ShaderRenderModifier(
     606            techTransparentBlend));
    568607    m->Model.ModShaderTransparentShadow = LitRenderModifierPtr(new ShaderRenderModifier(
    569608            techTransparentShadow));
     
    604643    m->Model.ModSolidPlayerColor = RenderModifierPtr(new SolidPlayerColorRender);
    605644    m->Model.ModTransparentUnlit = RenderModifierPtr(new TransparentRenderModifier);
     645    m->Model.ModTransparentOpaqueUnlit = RenderModifierPtr(new TransparentOpaqueRenderModifier);
     646    m->Model.ModTransparentBlendUnlit = RenderModifierPtr(new TransparentBlendRenderModifier);
    606647    m->Model.ModTransparentDepthShadow = RenderModifierPtr(new TransparentDepthShadowModifier);
    607648
     
    660701            m_Options.m_FancyWater=value;
    661702            break;
     703        case OPT_SHADOWPCF:
     704            m_Options.m_ShadowPCF=value;
     705            break;
    662706        default:
    663707            debug_warn(L"CRenderer::SetOptionBool: unknown option");
     
    677721        case OPT_FANCYWATER:
    678722            return m_Options.m_FancyWater;
     723        case OPT_SHADOWPCF:
     724            return m_Options.m_ShadowPCF;
    679725        default:
    680726            debug_warn(L"CRenderer::GetOptionBool: unknown option");
     
    812858        m->Model.ModShaderTransparent->SetShadowMap(m->shadow);
    813859        m->Model.ModShaderTransparent->SetLightEnv(m_LightEnv);
     860
     861        m->Model.ModShaderTransparentOpaque->SetShadowMap(m->shadow);
     862        m->Model.ModShaderTransparentOpaque->SetLightEnv(m_LightEnv);
     863
     864        m->Model.ModShaderTransparentBlend->SetShadowMap(m->shadow);
     865        m->Model.ModShaderTransparentBlend->SetLightEnv(m_LightEnv);
    814866
    815867        m->Model.ModNormal = m->Model.ModShaderNormal;
     
    822874        m->Model.ModSolidPlayerInstancing = m->Model.ModShaderSolidPlayerColorInstancing;
    823875        m->Model.ModTransparent = m->Model.ModShaderTransparent;
     876        m->Model.ModTransparentOpaque = m->Model.ModShaderTransparentOpaque;
     877        m->Model.ModTransparentBlend = m->Model.ModShaderTransparentBlend;
    824878
    825879        m->Model.Normal = m->Model.pal_NormalShader;
     
    838892        m->Model.ModPlayerInstancing = m->Model.ModPlayerUnlit;
    839893        m->Model.ModTransparent = m->Model.ModTransparentUnlit;
     894        m->Model.ModTransparentOpaque = m->Model.ModTransparentOpaqueUnlit;
     895        m->Model.ModTransparentBlend = m->Model.ModTransparentBlendUnlit;
    840896
    841897        m->Model.NormalInstancing = m->Model.pal_NormalFF;
     
    920976}
    921977
    922 void CRenderer::RenderPatches()
     978void CRenderer::RenderPatches(const CFrustum* frustum)
    923979{
    924980    PROFILE("render patches");
     981
     982    bool filtered = false;
     983    if (frustum)
     984    {
     985        if (!m->terrainRenderer->CullPatches(frustum))
     986            return;
     987
     988        filtered = true;
     989    }
    925990
    926991    // switch on wireframe if we need it
     
    932997    // render all the patches, including blend pass
    933998    if (GetRenderPath() == RP_SHADER)
    934         m->terrainRenderer->RenderTerrainShader((m_Caps.m_Shadows && m_Options.m_Shadows) ? m->shadow : 0);
     999        m->terrainRenderer->RenderTerrainShader((m_Caps.m_Shadows && m_Options.m_Shadows) ? m->shadow : 0, filtered);
    9351000    else
    936         m->terrainRenderer->RenderTerrain();
     1001        m->terrainRenderer->RenderTerrain(filtered);
    9371002
    9381003
     
    9541019
    9551020        // render tiles edges
    956         m->terrainRenderer->RenderPatches();
     1021        m->terrainRenderer->RenderPatches(filtered);
    9571022
    9581023        // set color for outline
     
    9611026
    9621027        // render outline of each patch
    963         m->terrainRenderer->RenderOutlines();
     1028        m->terrainRenderer->RenderOutlines(filtered);
    9641029
    9651030        // .. and restore the renderstates
     
    9691034}
    9701035
    971 void CRenderer::RenderModels()
     1036class CModelCuller : public CModelFilter
     1037{
     1038public:
     1039    CModelCuller(const CFrustum& frustum) : m_Frustum(frustum) { }
     1040
     1041    bool Filter(CModel *model)
     1042    {
     1043        return m_Frustum.IsBoxVisible(CVector3D(0, 0, 0), model->GetBoundsRec());
     1044    }
     1045
     1046private:
     1047    const CFrustum& m_Frustum;
     1048};
     1049
     1050void CRenderer::RenderModels(const CFrustum* frustum)
    9721051{
    9731052    PROFILE("render models");
    9741053
     1054    int flags = 0;
     1055    if (frustum)
     1056    {
     1057        flags = MODELFLAG_FILTERED;
     1058        CModelCuller culler(*frustum);
     1059        m->FilterModels(culler, flags);
     1060    }
     1061
    9751062    if (m_ModelRenderMode == WIREFRAME)
    9761063    {
     
    9791066
    9801067    m->CallModelRenderers(m->Model.ModNormal, m->Model.ModNormalInstancing,
    981             m->Model.ModPlayer, m->Model.ModPlayerInstancing, 0);
     1068            m->Model.ModPlayer, m->Model.ModPlayerInstancing, flags);
    9821069
    9831070    if (m_ModelRenderMode == WIREFRAME)
     
    9921079
    9931080        m->CallModelRenderers(m->Model.ModSolid, m->Model.ModSolidInstancing,
    994                 m->Model.ModSolid, m->Model.ModSolidInstancing, 0);
     1081                m->Model.ModSolid, m->Model.ModSolidInstancing, flags);
    9951082
    9961083        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     
    9981085}
    9991086
    1000 void CRenderer::RenderTransparentModels()
     1087void CRenderer::RenderTransparentModels(ETransparentMode transparentMode, const CFrustum* frustum)
    10011088{
    10021089    PROFILE("render transparent models");
     1090
     1091    int flags = 0;
     1092    if (frustum)
     1093    {
     1094        flags = MODELFLAG_FILTERED;
     1095        CModelCuller culler(*frustum);
     1096        m->Model.Transp->Filter(culler, flags);
     1097    }
    10031098
    10041099    // switch on wireframe if we need it
     
    10081103    }
    10091104
    1010     m->Model.Transp->Render(m->Model.ModTransparent, 0);
     1105    if (transparentMode == TRANSPARENT_OPAQUE)
     1106        m->Model.Transp->Render(m->Model.ModTransparentOpaque, flags);
     1107    else if (transparentMode == TRANSPARENT_BLEND)
     1108        m->Model.Transp->Render(m->Model.ModTransparentBlend, flags);
     1109    else
     1110        m->Model.Transp->Render(m->Model.ModTransparent, flags);
    10111111
    10121112    if (m_ModelRenderMode == WIREFRAME)
     
    10211121        glColor3f(1.0f, 0.0f, 0.0f);
    10221122
    1023         m->Model.Transp->Render(m->Model.ModSolid, 0);
     1123        m->Model.Transp->Render(m->Model.ModSolid, flags);
    10241124
    10251125        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     
    10351135    CMatrix3D view;
    10361136
    1037     glGetFloatv( GL_PROJECTION_MATRIX, &proj._11 );
    1038     glGetFloatv( GL_MODELVIEW_MATRIX, &view._11 );
    1039 
    1040     return( proj * view );
     1137    glGetFloatv(GL_PROJECTION_MATRIX, &proj._11);
     1138    glGetFloatv(GL_MODELVIEW_MATRIX, &view._11);
     1139
     1140    return proj*view;
    10411141}
    10421142
     
    10461146// SetObliqueFrustumClipping: change the near plane to the given clip plane (in world space)
    10471147// Based on code from Game Programming Gems 5, from http://www.terathon.com/code/oblique.html
    1048 // - cp is a clip plane in camera space (cp.Dot(v) = 0 for any vector v on the plane)
    1049 // - sign is 1 or -1, to specify the side to clip on
    1050 void CRenderer::SetObliqueFrustumClipping(const CVector4D& cp, int sign)
    1051 {
    1052     float matrix[16];
    1053     CVector4D q;
     1148// - worldPlane is a clip plane in world space (worldPlane.Dot(v) >= 0 for any vector v passing the clipping test)
     1149void CRenderer::SetObliqueFrustumClipping(const CVector4D& worldPlane)
     1150{
     1151    float matrix[16];
     1152    CVector4D q;
    10541153
    10551154    // First, we'll convert the given clip plane to camera space, then we'll
    10561155    // Get the view matrix and normal matrix (top 3x3 part of view matrix)
    1057     CMatrix3D viewMatrix;
    1058     m_ViewCamera.m_Orientation.GetInverse(viewMatrix);
    1059     CMatrix3D normalMatrix = viewMatrix;
    1060     normalMatrix._14 = 0;
    1061     normalMatrix._24 = 0;
    1062     normalMatrix._34 = 0;
    1063     normalMatrix._44 = 1;
    1064     normalMatrix._41 = 0;
    1065     normalMatrix._42 = 0;
    1066     normalMatrix._43 = 0;
    1067 
    1068     // Convert the normal to camera space
    1069     CVector4D planeNormal(cp.m_X, cp.m_Y, cp.m_Z, 0);
    1070     planeNormal = normalMatrix.Transform(planeNormal);
    1071     planeNormal.Normalize();
    1072 
    1073     // Find a point on the plane: we'll take the normal times -D
    1074     float oldD = cp.m_W;
    1075     CVector4D pointOnPlane(-oldD * cp.m_X, -oldD * cp.m_Y, -oldD * cp.m_Z, 1);
    1076     pointOnPlane = viewMatrix.Transform(pointOnPlane);
    1077     float newD = -pointOnPlane.Dot(planeNormal);
    1078 
    1079     // Now create a clip plane from the new normal and new D
    1080     CVector4D camPlane = planeNormal;
    1081     camPlane.m_W = newD;
    1082 
    1083     // Grab the current projection matrix from OpenGL
    1084     glGetFloatv(GL_PROJECTION_MATRIX, matrix);
     1156    CMatrix3D normalMatrix = m_ViewCamera.m_Orientation.GetTranspose();
     1157    CVector4D camPlane = normalMatrix.Transform(worldPlane);
     1158
     1159    // Grab the current projection matrix from OpenGL
     1160    glGetFloatv(GL_PROJECTION_MATRIX, matrix);
     1161
     1162    // Calculate the clip-space corner point opposite the clipping plane
     1163    // as (sgn(camPlane.x), sgn(camPlane.y), 1, 1) and
     1164    // transform it into camera space by multiplying it
     1165    // by the inverse of the projection matrix
    10851166   
    1086     // Calculate the clip-space corner point opposite the clipping plane
    1087     // as (sgn(camPlane.x), sgn(camPlane.y), 1, 1) and
    1088     // transform it into camera space by multiplying it
    1089     // by the inverse of the projection matrix
    1090    
    1091     q.m_X = (sgn(camPlane.m_X) + matrix[8]) / matrix[0];
    1092     q.m_Y = (sgn(camPlane.m_Y) + matrix[9]) / matrix[5];
    1093     q.m_Z = -1.0f;
    1094     q.m_W = (1.0f + matrix[10]) / matrix[14];
    1095    
    1096     // Calculate the scaled plane vector
    1097     CVector4D c = camPlane * (sign * 2.0f / camPlane.Dot(q));
    1098    
    1099     // Replace the third row of the projection matrix
    1100     matrix[2] = c.m_X;
    1101     matrix[6] = c.m_Y;
    1102     matrix[10] = c.m_Z + 1.0f;
    1103     matrix[14] = c.m_W;
    1104 
    1105     // Load it back into OpenGL
    1106     glMatrixMode(GL_PROJECTION);
    1107     glLoadMatrixf(matrix);
     1167    q.m_X = (sgn(camPlane.m_X) - matrix[8]/matrix[11]) / matrix[0];
     1168    q.m_Y = (sgn(camPlane.m_Y) - matrix[9]/matrix[11]) / matrix[5];
     1169    q.m_Z = 1.0f/matrix[11];
     1170    q.m_W = (1.0f - matrix[10]/matrix[11]) / matrix[14];
     1171
     1172    // Calculate the scaled plane vector
     1173    CVector4D c = camPlane * (2.0f * matrix[11] / camPlane.Dot(q));
     1174
     1175    // Replace the third row of the projection matrix
     1176    matrix[2] = c.m_X;
     1177    matrix[6] = c.m_Y;
     1178    matrix[10] = c.m_Z - matrix[11];
     1179    matrix[14] = c.m_W;
     1180
     1181    // Load it back into OpenGL
     1182    glMatrixMode(GL_PROJECTION);
     1183    glLoadMatrixf(matrix);
    11081184
    11091185    glMatrixMode(GL_MODELVIEW);
    11101186}
    1111 
    11121187
    11131188///////////////////////////////////////////////////////////////////////////////////////////////////
    11141189// RenderReflections: render the water reflections to the reflection texture
    1115 void CRenderer::RenderReflections()
     1190SScreenRect CRenderer::RenderReflections(const CBound& scissor)
    11161191{
    11171192    PROFILE("render reflections");
     
    11271202    // the whole screen despite being rendered into a square, and cover slightly more
    11281203    // of the view so we can see wavy reflections of slightly off-screen objects.
    1129     m_ViewCamera.m_Orientation.Translate(0, -wm.m_WaterHeight, 0);
    11301204    m_ViewCamera.m_Orientation.Scale(1, -1, 1);
    1131     m_ViewCamera.m_Orientation.Translate(0, wm.m_WaterHeight, 0);
     1205    m_ViewCamera.m_Orientation.Translate(0, 2*wm.m_WaterHeight, 0);
     1206    m_ViewCamera.UpdateFrustum(scissor);
     1207    m_ViewCamera.ClipFrustum(CVector4D(0, 1, 0, -wm.m_WaterHeight));
     1208
    11321209    SViewPort vp;
    11331210    vp.m_Height = wm.m_ReflectionTextureSize;
     
    11441221
    11451222    CVector4D camPlane(0, 1, 0, -wm.m_WaterHeight);
    1146     SetObliqueFrustumClipping(camPlane, -1);
     1223    SetObliqueFrustumClipping(camPlane);
    11471224
    11481225    // Save the model-view-projection matrix so the shaders can use it for projective texturing
    11491226    wm.m_ReflectionMatrix = GetModelViewProjectionMatrix();
    11501227
    1151     // Disable backface culling so trees render properly (it might also be possible to flip
    1152     // the culling direction here, but this seems to lead to problems)
    1153     glDisable(GL_CULL_FACE);
    1154 
    1155     // Make the depth buffer work backwards; there seems to be some oddness with
    1156     // oblique frustum clipping and the "sign" parameter here
    1157     glClearDepth(0);
    1158     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    1159     glDepthFunc(GL_GEQUAL);
    1160 
    1161     // Render sky, terrain and models
    1162     m->skyManager.RenderSky();
    1163     ogl_WarnIfError();
    1164     RenderPatches();
    1165     ogl_WarnIfError();
    1166     RenderModels();
    1167     ogl_WarnIfError();
    1168     RenderTransparentModels();
    1169     ogl_WarnIfError();
    1170 
    1171     // Copy the image to a texture
    1172     pglActiveTextureARB(GL_TEXTURE0_ARB);
    1173     glEnable(GL_TEXTURE_2D);
    1174     glBindTexture(GL_TEXTURE_2D, wm.m_ReflectionTexture);
    1175     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
    1176         (GLsizei)wm.m_ReflectionTextureSize, (GLsizei)wm.m_ReflectionTextureSize);
    1177 
    1178     //Reset old camera and re-enable backface culling
     1228    SScreenRect screenScissor;
     1229    screenScissor.x1 = (GLint)floor((scissor[0].X*0.5f+0.5f)*vp.m_Width);
     1230    screenScissor.y1 = (GLint)floor((scissor[0].Y*0.5f+0.5f)*vp.m_Height);
     1231    screenScissor.x2 = (GLint)ceil((scissor[1].X*0.5f+0.5f)*vp.m_Width);
     1232    screenScissor.y2 = (GLint)ceil((scissor[1].Y*0.5f+0.5f)*vp.m_Height);
     1233
     1234    if (screenScissor.x1 < screenScissor.x2 && screenScissor.y1 < screenScissor.y2)
     1235    {
     1236        glEnable(GL_SCISSOR_TEST);
     1237        glScissor(screenScissor.x1, screenScissor.y1, screenScissor.x2 - screenScissor.x1, screenScissor.y2 - screenScissor.y1);
     1238
     1239        glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
     1240
     1241        glFrontFace(GL_CW);
     1242
     1243        // Render sky, terrain and models
     1244        m->skyManager.RenderSky();
     1245        ogl_WarnIfError();
     1246        RenderPatches(&m_ViewCamera.GetFrustum());
     1247        ogl_WarnIfError();
     1248        RenderModels(&m_ViewCamera.GetFrustum());
     1249        ogl_WarnIfError();
     1250        RenderTransparentModels(TRANSPARENT_BLEND, &m_ViewCamera.GetFrustum());
     1251        ogl_WarnIfError();
     1252
     1253        glFrontFace(GL_CCW);
     1254
     1255        glDisable(GL_SCISSOR_TEST);
     1256
     1257        // Copy the image to a texture
     1258        pglActiveTextureARB(GL_TEXTURE0_ARB);
     1259        glEnable(GL_TEXTURE_2D);
     1260        glBindTexture(GL_TEXTURE_2D, wm.m_ReflectionTexture);
     1261        glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
     1262                screenScissor.x1, screenScissor.y1,
     1263                screenScissor.x1, screenScissor.y1,
     1264                screenScissor.x2 - screenScissor.x1, screenScissor.y2 - screenScissor.y1);
     1265    }
     1266
     1267    // Reset old camera
    11791268    m_ViewCamera = normalCamera;
    11801269    m->SetOpenGLCamera(m_ViewCamera);
    11811270
    1182     glEnable(GL_CULL_FACE);
    1183     //glClearDepth(1);
    1184     //glClear(GL_DEPTH_BUFFER_BIT);
    1185     //glDepthFunc(GL_LEQUAL);
     1271    return screenScissor;
    11861272}
    11871273
     
    11891275///////////////////////////////////////////////////////////////////////////////////////////////////
    11901276// RenderRefractions: render the water refractions to the refraction texture
    1191 void CRenderer::RenderRefractions()
     1277SScreenRect CRenderer::RenderRefractions(const CBound &scissor)
    11921278{
    11931279    PROFILE("render refractions");
     
    12021288    // the whole screen despite being rendered into a square, and cover slightly more
    12031289    // of the view so we can see wavy refractions of slightly off-screen objects.
     1290    m_ViewCamera.UpdateFrustum(scissor);
     1291    m_ViewCamera.ClipFrustum(CVector4D(0, -1, 0, wm.m_WaterHeight));
     1292
    12041293    SViewPort vp;
    12051294    vp.m_Height = wm.m_RefractionTextureSize;
     
    12121301    scaleMat.SetScaling(m_Height/float(std::max(1, m_Width)), 1.0f, 1.0f);
    12131302    m_ViewCamera.m_ProjMat = scaleMat * m_ViewCamera.m_ProjMat;
     1303
    12141304    m->SetOpenGLCamera(m_ViewCamera);
    12151305
    1216     CVector4D camPlane(0, 1, 0, -wm.m_WaterHeight);
    1217     SetObliqueFrustumClipping(camPlane, -1);
     1306    CVector4D camPlane(0, -1, 0, wm.m_WaterHeight);
     1307    SetObliqueFrustumClipping(camPlane);
    12181308
    12191309    // Save the model-view-projection matrix so the shaders can use it for projective texturing
    12201310    wm.m_RefractionMatrix = GetModelViewProjectionMatrix();
    12211311
    1222     // Make the depth buffer work backwards; there seems to be some oddness with
    1223     // oblique frustum clipping and the "sign" parameter here
    1224     glClearDepth(0);
    1225     glClearColor(0.5f, 0.5f, 0.5f, 1.0f);   // a neutral gray to blend in with shores
    1226     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    1227     glDepthFunc(GL_GEQUAL);
    1228 
    1229     // Render terrain and models
    1230     RenderPatches();
    1231     ogl_WarnIfError();
    1232     RenderModels();
    1233     ogl_WarnIfError();
    1234     RenderTransparentModels();
    1235     ogl_WarnIfError();
    1236 
    1237     // Copy the image to a texture
    1238     pglActiveTextureARB(GL_TEXTURE0_ARB);
    1239     glEnable(GL_TEXTURE_2D);
    1240     glBindTexture(GL_TEXTURE_2D, wm.m_RefractionTexture);
    1241     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
    1242         (GLsizei)wm.m_RefractionTextureSize, (GLsizei)wm.m_RefractionTextureSize);
    1243 
    1244     //Reset old camera and re-enable backface culling
     1312    SScreenRect screenScissor;
     1313    screenScissor.x1 = (GLint)floor((scissor[0].X*0.5f+0.5f)*vp.m_Width);
     1314    screenScissor.y1 = (GLint)floor((scissor[0].Y*0.5f+0.5f)*vp.m_Height);
     1315    screenScissor.x2 = (GLint)ceil((scissor[1].X*0.5f+0.5f)*vp.m_Width);
     1316    screenScissor.y2 = (GLint)ceil((scissor[1].Y*0.5f+0.5f)*vp.m_Height);
     1317    if (screenScissor.x1 < screenScissor.x2 && screenScissor.y1 < screenScissor.y2)
     1318    {
     1319        glEnable(GL_SCISSOR_TEST);
     1320        glScissor(screenScissor.x1, screenScissor.y1, screenScissor.x2 - screenScissor.x1, screenScissor.y2 - screenScissor.y1);
     1321
     1322        glClearColor(0.5f, 0.5f, 0.5f, 1.0f);       // a neutral gray to blend in with shores
     1323        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
     1324
     1325        // Render terrain and models
     1326        RenderPatches(&m_ViewCamera.GetFrustum());
     1327        ogl_WarnIfError();
     1328        RenderModels(&m_ViewCamera.GetFrustum());
     1329        ogl_WarnIfError();
     1330        RenderTransparentModels(TRANSPARENT_BLEND, &m_ViewCamera.GetFrustum());
     1331        ogl_WarnIfError();
     1332
     1333        glDisable(GL_SCISSOR_TEST);
     1334
     1335        // Copy the image to a texture
     1336        pglActiveTextureARB(GL_TEXTURE0_ARB);
     1337        glEnable(GL_TEXTURE_2D);
     1338        glBindTexture(GL_TEXTURE_2D, wm.m_RefractionTexture);
     1339        glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
     1340                screenScissor.x1, screenScissor.y1,
     1341                screenScissor.x1, screenScissor.y1,
     1342                screenScissor.x2 - screenScissor.x1, screenScissor.y2 - screenScissor.y1);
     1343    }
     1344
     1345    // Reset old camera
    12451346    m_ViewCamera = normalCamera;
    12461347    m->SetOpenGLCamera(m_ViewCamera);
    12471348
    1248     glEnable(GL_CULL_FACE);
    1249     glClearDepth(1);
    1250     glDepthFunc(GL_LEQUAL);
     1349    return screenScissor;
    12511350}
    12521351
     
    14361535    ogl_WarnIfError();
    14371536
    1438     if (m_WaterManager->m_RenderWater && m_WaterManager->WillRenderFancyWater())
    1439     {
    1440         // render reflected and refracted scenes, then re-clear the screen
    1441         RenderReflections();
    1442         RenderRefractions();
    1443         glClearColor(m_ClearColor[0],m_ClearColor[1],m_ClearColor[2],m_ClearColor[3]);
    1444         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
     1537    CBound waterScissor;
     1538    if (m_WaterManager->m_RenderWater)
     1539    {
     1540        waterScissor = m->terrainRenderer->ScissorWater(m_ViewCamera.GetViewProjection());
     1541        if (waterScissor.GetVolume() > 0 && m_WaterManager->WillRenderFancyWater())
     1542        {
     1543            SScreenRect reflectionScissor = RenderReflections(waterScissor);
     1544            SScreenRect refractionScissor = RenderRefractions(waterScissor);
     1545            SScreenRect dirty;
     1546            dirty.x1 = std::min(reflectionScissor.x1, refractionScissor.x1);
     1547            dirty.y1 = std::min(reflectionScissor.y1, refractionScissor.y1);
     1548            dirty.x2 = std::max(reflectionScissor.x2, refractionScissor.x2);
     1549            dirty.y2 = std::max(reflectionScissor.y2, refractionScissor.y2);
     1550            if (dirty.x1 < dirty.x2 && dirty.y1 < dirty.y2)
     1551            {
     1552                glEnable(GL_SCISSOR_TEST);
     1553                glScissor(dirty.x1, dirty.y1, dirty.x2 - dirty.x1, dirty.y2 - dirty.y1);
     1554                glClearColor(m_ClearColor[0], m_ClearColor[1], m_ClearColor[2], m_ClearColor[3]);
     1555                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
     1556                glDisable(GL_SCISSOR_TEST);
     1557            }
     1558        }
    14451559    }
    14461560
     
    14681582    ogl_WarnIfError();
    14691583
    1470     // render transparent stuff, so it can overlap models/terrain
    1471     RenderTransparentModels();
    1472     ogl_WarnIfError();
    1473 
    14741584    // render water
    1475     if (m_WaterManager->m_RenderWater && g_Game)
    1476     {
     1585    if (m_WaterManager->m_RenderWater && g_Game && waterScissor.GetVolume() > 0)
     1586    {
     1587        // render transparent stuff, but only the solid parts that can occlude block water
     1588        RenderTransparentModels(TRANSPARENT_OPAQUE);
     1589        ogl_WarnIfError();
     1590
    14771591        m->terrainRenderer->RenderWater();
    14781592        ogl_WarnIfError();
    1479        
    1480         // render transparent stuff again, so it can overlap the water
    1481         RenderTransparentModels();
     1593
     1594        // render transparent stuff again, but only the blended parts that overlap water
     1595        RenderTransparentModels(TRANSPARENT_BLEND);
    14821596        ogl_WarnIfError();
    1483        
    1484         // TODO: Maybe think of a better way to deal with transparent objects;
    1485         // they can appear both under and above water (seaweed vs. trees), but doing
    1486         // 2 renders causes (a) inefficiency and (b) darker over-water objects (e.g.
    1487         // trees) than usual because the transparent bits get overwritten twice.
    1488         // This doesn't look particularly bad, but it is noticeable if you try
    1489         // turning the water off. On the other hand every user will have water
    1490         // on all the time, so it might not be worth worrying about.
     1597    }
     1598    else
     1599    {
     1600        // render transparent stuff, so it can overlap models/terrain
     1601        RenderTransparentModels(TRANSPARENT);
     1602        ogl_WarnIfError();
    14911603    }
    14921604
     
    19322044}
    19332045
     2046jsval CRenderer::JSI_GetShadowPCF(JSContext*)
     2047{
     2048    return ToJSVal(m_Options.m_ShadowPCF);
     2049}
     2050
     2051void CRenderer::JSI_SetShadowPCF(JSContext* ctx, jsval newval)
     2052{
     2053    if (!ToPrimitive(ctx, newval, m_Options.m_ShadowPCF))
     2054        return;
     2055
     2056    ReloadShaders();
     2057}
     2058
    19342059jsval CRenderer::JSI_GetSky(JSContext*)
    19352060{
     
    19562081    AddProperty(L"depthTextureBits", &CRenderer::JSI_GetDepthTextureBits, &CRenderer::JSI_SetDepthTextureBits);
    19572082    AddProperty(L"shadowAlphaFix", &CRenderer::JSI_GetShadowAlphaFix, &CRenderer::JSI_SetShadowAlphaFix);
     2083    AddProperty(L"shadowPCF", &CRenderer::JSI_GetShadowPCF, &CRenderer::JSI_SetShadowPCF);
    19582084    AddProperty(L"skipSubmit", &CRenderer::m_SkipSubmit);
    19592085    AddProperty(L"skySet", &CRenderer::JSI_GetSky, &CRenderer::JSI_SetSky);
  • ps/trunk/source/renderer/Renderer.h

    r9410 r9814  
    5050enum ERenderMode { WIREFRAME, SOLID, EDGED_FACES };
    5151
     52// transparency modes
     53enum ETransparentMode { TRANSPARENT, TRANSPARENT_OPAQUE, TRANSPARENT_BLEND };
     54
    5255// stream flags
    5356#define STREAM_POS (1 << 0)
     
    6669#define g_Renderer CRenderer::GetSingleton()
    6770
     71struct SScreenRect
     72{
     73    GLint x1, y1, x2, y2;
     74};
     75
    6876///////////////////////////////////////////////////////////////////////////////////////////
    6977// CRenderer: base renderer class - primary interface to the rendering engine
     
    8290        OPT_SHADOWS,
    8391        OPT_FANCYWATER,
    84         OPT_LODBIAS
     92        OPT_LODBIAS,
     93        OPT_SHADOWPCF
    8594    };
    8695
     
    105114        // number of terrain triangles drawn
    106115        size_t m_TerrainTris;
     116        // number of water triangles drawn
     117        size_t m_WaterTris;
    107118        // number of (non-transparent) model triangles drawn
    108119        size_t m_ModelTris;
     
    122133        bool m_ShadowAlphaFix;
    123134        bool m_ARBProgramShadow;
     135        bool m_ShadowPCF;
    124136    } m_Options;
    125137
     
    316328    jsval JSI_GetShadowAlphaFix(JSContext*);
    317329    void JSI_SetShadowAlphaFix(JSContext* ctx, jsval newval);
     330    jsval JSI_GetShadowPCF(JSContext*);
     331    void JSI_SetShadowPCF(JSContext* ctx, jsval newval);
    318332    jsval JSI_GetSky(JSContext*);
    319333    void JSI_SetSky(JSContext* ctx, jsval newval);
     
    332346
    333347    // patch rendering stuff
    334     void RenderPatches();
     348    void RenderPatches(const CFrustum* frustum = 0);
    335349
    336350    // model rendering stuff
    337     void RenderModels();
    338     void RenderTransparentModels();
     351    void RenderModels(const CFrustum* frustum = 0);
     352    void RenderTransparentModels(ETransparentMode transparentMode, const CFrustum* frustum = 0);
    339353
    340354    void RenderSilhouettes();
     
    346360
    347361    // render water reflection and refraction textures
    348     void RenderReflections();
    349     void RenderRefractions();
     362    SScreenRect RenderReflections(const CBound& scissor);
     363    SScreenRect RenderRefractions(const CBound& scissor);
    350364
    351365    // debugging
     
    353367
    354368    // enable oblique frustum clipping with the given clip plane
    355     void SetObliqueFrustumClipping(const CVector4D& clipPlane, int sign);
     369    void SetObliqueFrustumClipping(const CVector4D& clipPlane);
    356370
    357371    void ReloadShaders();
  • ps/trunk/source/renderer/ShadowMap.cpp

    r9189 r9814  
    7979    GLuint DummyTexture;
    8080
     81    float FilterOffsets[8];
     82
    8183    // Helper functions
    8284    void CalcShadowMatrices();
     
    222224    ShadowBound.IntersectFrustumConservative(LightspaceCamera.GetFrustum());
    223225
     226    // round off the shadow boundaries to sane increments to help reduce swim effect
     227    float boundInc = 16.0f;
     228    ShadowBound[0].X = floor(ShadowBound[0].X / boundInc) * boundInc;
     229    ShadowBound[0].Y = floor(ShadowBound[0].Y / boundInc) * boundInc;
     230    ShadowBound[1].X = ceil(ShadowBound[1].X / boundInc) * boundInc;
     231    ShadowBound[1].Y = ceil(ShadowBound[1].Y / boundInc) * boundInc;
     232
    224233    // minimum Z bound must not be clipped too much, because objects that lie outside
    225234    // the shadow bounds cannot cast shadows either
     
    243252    scale.Z = 2.0 / scale.Z;
    244253
     254    // make sure a given world position falls on a consistent shadowmap texel fractional offset
     255    float offsetX = fmod(ShadowBound[0].X - LightTransform._14, 2.0f/(scale.X*EffectiveWidth));
     256    float offsetY = fmod(ShadowBound[0].Y - LightTransform._24, 2.0f/(scale.Y*EffectiveHeight));
     257
    245258    LightProjection.SetZero();
    246259    LightProjection._11 = scale.X;
    247     LightProjection._14 = shift.X * scale.X;
     260    LightProjection._14 = (shift.X + offsetX) * scale.X;
    248261    LightProjection._22 = scale.Y;
    249     LightProjection._24 = shift.Y * scale.Y;
     262    LightProjection._24 = (shift.Y + offsetY) * scale.Y;
    250263    LightProjection._33 = scale.Z;
    251264    LightProjection._34 = shift.Z * scale.Z + renderer.m_ShadowZBias;
     
    256269    // and then concatenating all matrices that have been calculated so far
    257270    CMatrix3D lightToTex;
    258     float texscalex = (float)EffectiveWidth / (float)Width;
    259     float texscaley = (float)EffectiveHeight / (float)Height;
    260     float texscalez = 1.0;
    261 
    262     texscalex = texscalex / (ShadowBound[1].X - ShadowBound[0].X);
    263     texscaley = texscaley / (ShadowBound[1].Y - ShadowBound[0].Y);
    264     texscalez = texscalez / (ShadowBound[1].Z - ShadowBound[0].Z);
     271    float texscalex = scale.X * 0.5f * (float)EffectiveWidth / (float)Width;
     272    float texscaley = scale.Y * 0.5f * (float)EffectiveHeight / (float)Height;
     273    float texscalez = scale.Z * 0.5f;
    265274
    266275    lightToTex.SetZero();
    267276    lightToTex._11 = texscalex;
    268     lightToTex._14 = -ShadowBound[0].X * texscalex;
     277    lightToTex._14 = (offsetX - ShadowBound[0].X) * texscalex;
    269278    lightToTex._22 = texscaley;
    270     lightToTex._24 = -ShadowBound[0].Y * texscaley;
     279    lightToTex._24 = (offsetY - ShadowBound[0].Y) * texscaley;
    271280    lightToTex._33 = texscalez;
    272281    lightToTex._34 = -ShadowBound[0].Z * texscalez;
     
    360369    glTexImage2D(GL_TEXTURE_2D, 0, format, Width, Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
    361370
    362     glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
     371    glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
    363372    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
    364373    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
     
    398407        g_Renderer.m_Options.m_Shadows = false;
    399408    }
     409
     410    FilterOffsets[0] = -0.4f/Width;
     411    FilterOffsets[1] = 1.0f/Height;
     412
     413    FilterOffsets[2] = -1.0f/Width;
     414    FilterOffsets[3] = -0.4f/Height;
     415
     416    FilterOffsets[4] = 0.4f/Width;
     417    FilterOffsets[5] = -1.0f/Height;
     418
     419    FilterOffsets[6] = 1.0f/Width;
     420    FilterOffsets[7] = 0.4f/Height;
    400421}
    401422
     
    497518}
    498519
     520const float* ShadowMap::GetFilterOffsets() const
     521{
     522    return m->FilterOffsets;
     523}
    499524
    500525//////////////////////////////////////////////////////////////////////////////
  • ps/trunk/source/renderer/ShadowMap.h

    r9188 r9814  
    119119    void RenderDebugDisplay();
    120120
     121    /**
     122     * Get offsets for PCF filtering.
     123     */
     124    const float* GetFilterOffsets() const;
     125
    121126private:
    122127    ShadowMapInternals* m;
  • ps/trunk/source/renderer/TerrainRenderer.cpp

    r9362 r9814  
    7777    /// Patches that were submitted for this frame
    7878    std::vector<CPatchRData*> visiblePatches;
     79    std::vector<CPatchRData*> filteredPatches;
    7980
    8081    /// Decals that were submitted for this frame
    8182    std::vector<CDecalRData*> visibleDecals;
     83    std::vector<CDecalRData*> filteredDecals;
    8284
    8385    /// Fancy water shader
     
    165167
    166168///////////////////////////////////////////////////////////////////
     169// Culls patches and decals against a frustum.
     170bool TerrainRenderer::CullPatches(const CFrustum* frustum)
     171{
     172    m->filteredPatches.clear();
     173    for (std::vector<CPatchRData*>::iterator it = m->visiblePatches.begin(); it != m->visiblePatches.end(); it++)
     174    {
     175        if (frustum->IsBoxVisible(CVector3D(0, 0, 0), (*it)->GetPatch()->GetBounds()))
     176            m->filteredPatches.push_back(*it);
     177    }
     178
     179    m->filteredDecals.clear();
     180    for (std::vector<CDecalRData*>::iterator it = m->visibleDecals.begin(); it != m->visibleDecals.end(); it++)
     181    {
     182        if (frustum->IsBoxVisible(CVector3D(0, 0, 0), (*it)->GetDecal()->GetBounds()))
     183            m->filteredDecals.push_back(*it);
     184    }
     185
     186    return !m->filteredPatches.empty() || !m->filteredDecals.empty();
     187}
     188
     189///////////////////////////////////////////////////////////////////
    167190// Full-featured terrain rendering with blending and everything
    168 void TerrainRenderer::RenderTerrain()
     191void TerrainRenderer::RenderTerrain(bool filtered)
    169192{
    170193    ENSURE(m->phase == Phase_Render);
     194
     195    std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
     196    std::vector<CDecalRData*>& visibleDecals = filtered ? m->filteredDecals : m->visibleDecals;
     197    if (visiblePatches.empty() && visibleDecals.empty())
     198        return;
    171199
    172200    // render the solid black sides of the map first
     
    175203    glColor3f(0, 0, 0);
    176204    PROFILE_START("render terrain sides");
    177     for (size_t i = 0; i < m->visiblePatches.size(); ++i)
    178         m->visiblePatches[i]->RenderSides();
     205    for (size_t i = 0; i < visiblePatches.size(); ++i)
     206        visiblePatches[i]->RenderSides();
    179207    PROFILE_END("render terrain sides");
    180208
     
    199227   
    200228    PROFILE_START("render terrain base");
    201     CPatchRData::RenderBases(m->visiblePatches);
     229    CPatchRData::RenderBases(visiblePatches);
    202230    PROFILE_END("render terrain base");
    203231
     
    232260    // render blend passes for each patch
    233261    PROFILE_START("render terrain blends");
    234     CPatchRData::RenderBlends(m->visiblePatches);
     262    CPatchRData::RenderBlends(visiblePatches);
    235263    PROFILE_END("render terrain blends");
    236264
     
    256284
    257285    PROFILE_START("render terrain decals");
    258     for (size_t i = 0; i < m->visibleDecals.size(); ++i)
    259         m->visibleDecals[i]->Render(CShaderProgramPtr());
     286    for (size_t i = 0; i < visibleDecals.size(); ++i)
     287        visibleDecals[i]->Render(CShaderProgramPtr());
    260288    PROFILE_END("render terrain decals");
    261289
     
    324352
    325353    PROFILE_START("render terrain streams");
    326     CPatchRData::RenderStreams(m->visiblePatches, streamflags);
     354    CPatchRData::RenderStreams(visiblePatches, streamflags);
    327355    PROFILE_END("render terrain streams");
    328356
     
    364392        shader->BindTexture("shadowTex", shadow->GetTexture());
    365393        shader->Uniform("shadowTransform", shadow->GetTextureMatrix());
     394
     395        const float* offsets = shadow->GetFilterOffsets();
     396        shader->Uniform("shadowOffsets1", offsets[0], offsets[1], offsets[2], offsets[3]);
     397        shader->Uniform("shadowOffsets2", offsets[4], offsets[5], offsets[6], offsets[7]);
    366398    }
    367399
     
    374406}
    375407
    376 void TerrainRenderer::RenderTerrainShader(ShadowMap* shadow)
     408void TerrainRenderer::RenderTerrainShader(ShadowMap* shadow, bool filtered)
    377409{
    378410    ENSURE(m->phase == Phase_Render);
     411
     412    std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
     413    std::vector<CDecalRData*>& visibleDecals = filtered ? m->filteredDecals : m->visibleDecals;
     414    if (visiblePatches.empty() && visibleDecals.empty())
     415        return;
    379416
    380417    CShaderManager& shaderManager = g_Renderer.GetShaderManager();
     
    387424        if (g_Renderer.m_Caps.m_ARBProgramShadow && g_Renderer.m_Options.m_ARBProgramShadow)
    388425            defBasic["USE_FP_SHADOW"] = "1";
     426        if (g_Renderer.m_Options.m_ShadowPCF)
     427            defBasic["USE_SHADOW_PCF"] = "1";
    389428    }
    390429
     
    400439    glColor3f(0, 0, 0);
    401440    PROFILE_START("render terrain sides");
    402     for (size_t i = 0; i < m->visiblePatches.size(); ++i)
    403         m->visiblePatches[i]->RenderSides();
     441    for (size_t i = 0; i < visiblePatches.size(); ++i)
     442        visiblePatches[i]->RenderSides();
    404443    PROFILE_END("render terrain sides");
    405444
     
    412451
    413452    PROFILE_START("render terrain base");
    414     CPatchRData::RenderBases(m->visiblePatches);
     453    CPatchRData::RenderBases(visiblePatches);
    415454    PROFILE_END("render terrain base");
    416455
     
    438477    // render blend passes for each patch
    439478    PROFILE_START("render terrain blends");
    440     CPatchRData::RenderBlends(m->visiblePatches);
     479    CPatchRData::RenderBlends(visiblePatches);
    441480    PROFILE_END("render terrain blends");
    442481
     
    457496
    458497    PROFILE_START("render terrain decals");
    459     for (size_t i = 0; i < m->visibleDecals.size(); ++i)
    460         m->visibleDecals[i]->Render(shaderDecal);
     498    for (size_t i = 0; i < visibleDecals.size(); ++i)
     499        visibleDecals[i]->Render(shaderDecal);
    461500    PROFILE_END("render terrain decals");
    462501
     
    481520///////////////////////////////////////////////////////////////////
    482521// Render un-textured patches as polygons
    483 void TerrainRenderer::RenderPatches()
     522void TerrainRenderer::RenderPatches(bool filtered)
    484523{
    485524    ENSURE(m->phase == Phase_Render);
    486525
     526    std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
     527    if (visiblePatches.empty())
     528        return;
     529
    487530    glEnableClientState(GL_VERTEX_ARRAY);
    488     CPatchRData::RenderStreams(m->visiblePatches, STREAM_POS);
     531    CPatchRData::RenderStreams(visiblePatches, STREAM_POS);
    489532    glDisableClientState(GL_VERTEX_ARRAY);
    490533}
     
    493536///////////////////////////////////////////////////////////////////
    494537// Render outlines of submitted patches as lines
    495 void TerrainRenderer::RenderOutlines()
     538void TerrainRenderer::RenderOutlines(bool filtered)
    496539{
    497540    ENSURE(m->phase == Phase_Render);
    498541
     542    std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
     543    if (visiblePatches.empty())
     544        return;
     545
    499546    glEnableClientState(GL_VERTEX_ARRAY);
     547    for (size_t i = 0; i < visiblePatches.size(); ++i)
     548        visiblePatches[i]->RenderOutline();
     549    glDisableClientState(GL_VERTEX_ARRAY);
     550}
     551
     552
     553///////////////////////////////////////////////////////////////////
     554// Scissor rectangle of water patches
     555CBound TerrainRenderer::ScissorWater(const CMatrix3D &viewproj)
     556{
     557    CBound scissor;
    500558    for (size_t i = 0; i < m->visiblePatches.size(); ++i)
    501         m->visiblePatches[i]->RenderOutline();
    502     glDisableClientState(GL_VERTEX_ARRAY);
    503 }
    504 
    505 
    506 ///////////////////////////////////////////////////////////////////
    507 // Render water that is part of the terrain
    508 void TerrainRenderer::RenderWater()
    509 {
    510     PROFILE( "render water" );
    511 
    512     WaterManager* WaterMgr = g_Renderer.GetWaterManager();
    513 
    514     bool fancy = WaterMgr->WillRenderFancyWater();
     559    {
     560        CPatchRData* data = m->visiblePatches[i];
     561        const CBound& waterBounds = data->GetWaterBounds();
     562        if (waterBounds.IsEmpty())
     563            continue;
     564
     565        CVector4D v1 = viewproj.Transform(CVector4D(waterBounds[0].X, waterBounds[1].Y, waterBounds[0].Z, 1.0f));
     566        CVector4D v2 = viewproj.Transform(CVector4D(waterBounds[1].X, waterBounds[1].Y, waterBounds[0].Z, 1.0f));
     567        CVector4D v3 = viewproj.Transform(CVector4D(waterBounds[0].X, waterBounds[1].Y, waterBounds[1].Z, 1.0f));
     568        CVector4D v4 = viewproj.Transform(CVector4D(waterBounds[1].X, waterBounds[1].Y, waterBounds[1].Z, 1.0f));
     569        CBound screenBounds;
     570        #define ADDBOUND(v1, v2, v3, v4) \
     571            if (v1[2] >= -v1[3]) \
     572                screenBounds += CVector3D(v1[0], v1[1], v1[2]) * (1.0f / v1[3]); \
     573            else \
     574            { \
     575                float t = v1[2] + v1[3]; \
     576                if (v2[2] > -v2[3]) \
     577                { \
     578                    CVector4D c2 = v1 + (v2 - v1) * (t / (t - (v2[2] + v2[3]))); \
     579                    screenBounds += CVector3D(c2[0], c2[1], c2[2]) * (1.0f / c2[3]); \
     580                } \
     581                if (v3[2] > -v3[3]) \
     582                { \
     583                    CVector4D c3 = v1 + (v3 - v1) * (t / (t - (v3[2] + v3[3]))); \
     584                    screenBounds += CVector3D(c3[0], c3[1], c3[2]) * (1.0f / c3[3]); \
     585                } \
     586                if (v4[2] > -v4[3]) \
     587                { \
     588                    CVector4D c4 = v1 + (v4 - v1) * (t / (t - (v4[2] + v4[3]))); \
     589                    screenBounds += CVector3D(c4[0], c4[1], c4[2]) * (1.0f / c4[3]); \
     590                } \
     591            }
     592        ADDBOUND(v1, v2, v3, v4);
     593        ADDBOUND(v2, v1, v3, v4);
     594        ADDBOUND(v3, v1, v2, v4);
     595        ADDBOUND(v4, v1, v2, v3);
     596        #undef ADDBOUND
     597        if (screenBounds[0].X >= 1.0f || screenBounds[1].X <= -1.0f || screenBounds[0].Y >= 1.0f || screenBounds[1].Y <= -1.0f)
     598            continue;
     599        scissor += screenBounds;
     600    }
     601    return CBound(CVector3D(clamp(scissor[0].X, -1.0f, 1.0f), clamp(scissor[0].Y, -1.0f, 1.0f), -1.0f),
     602                  CVector3D(clamp(scissor[1].X, -1.0f, 1.0f), clamp(scissor[1].Y, -1.0f, 1.0f), 1.0f));
     603}
     604
     605// Render fancy water
     606bool TerrainRenderer::RenderFancyWater()
     607{
     608    PROFILE("render fancy water");
    515609
    516610    // If we're using fancy water, make sure its shader is loaded
    517     if(fancy && !m->fancyWaterShader)
     611    if (!m->fancyWaterShader)
    518612    {
    519613        Handle h = ogl_program_load(g_VFS, L"shaders/water_high.xml");
     
    522616            LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n");
    523617            g_Renderer.m_Options.m_FancyWater = false;
    524             fancy = false;
     618            return false;
    525619        }
    526620        else
     
    529623        }
    530624    }
    531     CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); // TODO: stop using g_Game
    532 
     625
     626    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
    533627    CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture();
    534628   
     
    539633
    540634    double time = WaterMgr->m_WaterTexTimer;
    541 
    542635    double period = 1.6;
    543636    int curTex = (int)(time*60/period) % 60;
    544637
    545     if(fancy)
    546     {
    547         WaterMgr->m_NormalMap[curTex]->Bind();
    548     }
    549     else
    550     {
    551         WaterMgr->m_WaterTexture[curTex]->Bind();
    552     }
     638    WaterMgr->m_NormalMap[curTex]->Bind();
    553639
    554640    // Shift the texture coordinates by these amounts to make the water "flow"
    555641    float tx = -fmod(time, 81.0)/81.0;
    556642    float ty = -fmod(time, 34.0)/34.0;
    557 
    558     if(!fancy)
    559     {
    560         // Perform the shifting by modifying the texture matrix
    561         glMatrixMode(GL_TEXTURE);
    562         glLoadIdentity();
    563         glTranslatef(tx, ty, 0);
    564 
    565         // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
    566         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    567         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
    568         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
    569         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
    570         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
    571         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
    572         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
    573         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
    574         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    575 
    576         // Multiply by LOS texture
    577         losTexture.BindTexture(1);
    578         pglClientActiveTextureARB(GL_TEXTURE1);
    579         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    580 
    581         glLoadMatrixf(losTexture.GetTextureMatrix());
    582 
    583         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    584         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
    585         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
    586         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
    587         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
    588         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
    589         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
    590         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
    591         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    592     }
     643    float repeatPeriod = WaterMgr->m_RepeatPeriod;
    593644
    594645    // Set the proper LOD bias
     
    598649    CVector3D camPos = camera.m_Orientation.GetTranslation();
    599650
    600     GLint vertexDepth = 0;  // water depth attribute, if using fancy water
    601 
    602     if(fancy)
    603     {
    604         // Bind reflection and refraction textures on texture units 1 and 2
    605         pglActiveTextureARB( GL_TEXTURE1_ARB );
    606         glEnable( GL_TEXTURE_2D );
    607         glBindTexture( GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture );
    608         pglActiveTextureARB( GL_TEXTURE2_ARB );
    609         glEnable( GL_TEXTURE_2D );
    610         glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture );
    611 
    612         losTexture.BindTexture(3);
    613 
    614         // Bind water shader and set arguments
    615         ogl_program_use( m->fancyWaterShader );
    616 
    617         GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" );
    618         GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" );
    619         GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" );
    620         GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" );
    621         GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" );
    622         GLint specularStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "specularStrength" );
    623         GLint waviness = ogl_program_get_uniform_location( m->fancyWaterShader, "waviness" );
    624         GLint murkiness = ogl_program_get_uniform_location( m->fancyWaterShader, "murkiness" );
    625         GLint fullDepth = ogl_program_get_uniform_location( m->fancyWaterShader, "fullDepth" );
    626         GLint tint = ogl_program_get_uniform_location( m->fancyWaterShader, "tint" );
    627         GLint reflectionTint = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTint" );
    628         GLint reflectionTintStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTintStrength" );
    629         GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" );
    630         GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" );
    631         GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" );
    632         GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" );
    633         GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" );
    634         GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" );
    635         GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" );
    636         GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" );
    637 
    638         const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
    639         pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X );
    640         pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X );
    641         pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X );
    642         pglUniform1fARB( shininess, WaterMgr->m_Shininess );
    643         pglUniform1fARB( specularStrength, WaterMgr->m_SpecularStrength );
    644         pglUniform1fARB( waviness, WaterMgr->m_Waviness );
    645         pglUniform1fARB( murkiness, WaterMgr->m_Murkiness );
    646         pglUniform1fARB( fullDepth, WaterMgr->m_WaterFullDepth );
    647         pglUniform3fvARB( tint, 1, WaterMgr->m_WaterTint.FloatArray() );
    648         pglUniform1fARB( reflectionTintStrength, WaterMgr->m_ReflectionTintStrength );
    649         pglUniform3fvARB( reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray() );
    650         pglUniform4fARB( translation, tx, ty, 0, 0 );
    651         pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 );
    652         pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 );
    653         pglUniformMatrix4fvARB( losMatrix, 1, false, losTexture.GetTextureMatrix() );
    654         pglUniform1iARB( normalMap, 0 );        // texture unit 0
    655         pglUniform1iARB( reflectionMap, 1 );    // texture unit 1
    656         pglUniform1iARB( refractionMap, 2 );    // texture unit 2
    657         pglUniform1iARB( losMap, 3 );           // texture unit 3
    658         pglUniform3fvARB( cameraPos, 1, &camPos.X );
    659 
    660         vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
    661     }
    662    
    663     float repeatPeriod = (fancy ? WaterMgr->m_RepeatPeriod : 16.0f);
    664 
    665     glBegin(GL_QUADS);
    666 
    667     for(size_t i=0; i<m->visiblePatches.size(); i++)
    668     {
    669         CPatch* patch = m->visiblePatches[i]->GetPatch();
    670 
    671         for(ssize_t dx=0; dx<PATCH_SIZE; dx++)
    672         {
    673             for(ssize_t dz=0; dz<PATCH_SIZE; dz++)
    674             {
    675                 ssize_t x = (patch->m_X*PATCH_SIZE + dx);
    676                 ssize_t z = (patch->m_Z*PATCH_SIZE + dz);
    677 
    678                 // Some offsets used to go around counterclockwise while keeping code concise
    679                 const int DX[] = {1,1,0,0};
    680                 const int DZ[] = {0,1,1,0};
    681 
    682                 // is any corner of the tile below the water height? if not, no point rendering it
    683                 bool shouldRender = false;
    684                 for (int j = 0; j < 4; j++)
    685                 {
    686                     float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]);
    687                     if (terrainHeight < WaterMgr->m_WaterHeight)
    688                     {
    689                         shouldRender = true;
    690                         break;
    691                     }
    692                 }
    693                 if (!shouldRender)
    694                     continue;
    695 
    696                 for (int j=0; j<4; j++)
    697                 {
    698                     ssize_t ix = x + DX[j];
    699                     ssize_t iz = z + DZ[j];
    700 
    701                     float vertX = ix * CELL_SIZE;
    702                     float vertZ = iz * CELL_SIZE;
    703 
    704                     float terrainHeight = terrain->GetVertexGroundLevel(ix, iz);
    705 
    706                     if (fancy)
    707                     {
    708                         pglVertexAttrib1fARB(vertexDepth, WaterMgr->m_WaterHeight - terrainHeight);
    709                         pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod);
    710                         glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
    711                     }
    712                     else
    713                     {
    714                         float alpha = clamp( (WaterMgr->m_WaterHeight - terrainHeight) / WaterMgr->m_WaterFullDepth + WaterMgr->m_WaterAlphaOffset,
    715                                               WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha);
    716 
    717                         // (Crappy) fresnel effect
    718                         CVector3D CamFaceVertex=CVector3D(vertX,WaterMgr->m_WaterHeight,vertZ)-camPos;
    719                         CamFaceVertex.Normalize();
    720                         float FresnelScalar = CamFaceVertex.Dot(CVector3D(0.0f, -1.0f, 0.0f));
    721                         // Invert and set boundaries
    722                         FresnelScalar = 1.f - (FresnelScalar * 0.6);
    723 
    724                         glColor4f(WaterMgr->m_WaterColor.r,
    725                                   WaterMgr->m_WaterColor.g,
    726                                   WaterMgr->m_WaterColor.b,
    727                                   alpha * FresnelScalar);
    728                         pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod);
    729                         pglMultiTexCoord3fARB(GL_TEXTURE1, vertX, WaterMgr->m_WaterHeight, vertZ);
    730                         glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
    731                     }
    732 
    733                 }
    734             }   //end of x loop
    735         }   //end of z loop
    736     }
    737     glEnd();
    738 
    739     if (fancy)
    740     {
    741         // Unbind the LOS/refraction/reflection textures and the shader
    742 
    743         g_Renderer.BindTexture(3, 0);
    744         g_Renderer.BindTexture(2, 0);
    745         g_Renderer.BindTexture(1, 0);
    746 
    747         pglActiveTextureARB(GL_TEXTURE0_ARB);
    748 
    749         ogl_program_use(0);
    750     }
    751 
    752     if (!fancy)
    753     {
    754         g_Renderer.BindTexture(1, 0);
    755         pglClientActiveTextureARB(GL_TEXTURE1_ARB);
    756         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    757 
    758         glLoadIdentity();
    759 
    760         pglActiveTextureARB(GL_TEXTURE0_ARB);
    761         pglClientActiveTextureARB(GL_TEXTURE0_ARB);
    762 
    763         // Clean up the texture matrix and blend mode
    764         glLoadIdentity();
    765         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    766     }
    767 
    768     glMatrixMode(GL_MODELVIEW);
     651    // Bind reflection and refraction textures on texture units 1 and 2
     652    pglActiveTextureARB(GL_TEXTURE1_ARB);
     653    glEnable(GL_TEXTURE_2D);
     654    glBindTexture(GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture);
     655    pglActiveTextureARB(GL_TEXTURE2_ARB);
     656    glEnable(GL_TEXTURE_2D);
     657    glBindTexture(GL_TEXTURE_2D, WaterMgr->m_RefractionTexture);
     658
     659    losTexture.BindTexture(3);
     660
     661    // Bind water shader and set arguments
     662    ogl_program_use(m->fancyWaterShader);
     663
     664    GLint ambient = ogl_program_get_uniform_location(m->fancyWaterShader, "ambient");
     665    GLint sunDir = ogl_program_get_uniform_location(m->fancyWaterShader, "sunDir");
     666    GLint sunColor = ogl_program_get_uniform_location(m->fancyWaterShader, "sunColor");
     667    GLint cameraPos = ogl_program_get_uniform_location(m->fancyWaterShader, "cameraPos");
     668    GLint shininess = ogl_program_get_uniform_location(m->fancyWaterShader, "shininess");
     669    GLint specularStrength = ogl_program_get_uniform_location(m->fancyWaterShader, "specularStrength");
     670    GLint waviness = ogl_program_get_uniform_location(m->fancyWaterShader, "waviness");
     671    GLint murkiness = ogl_program_get_uniform_location(m->fancyWaterShader, "murkiness");
     672    GLint fullDepth = ogl_program_get_uniform_location(m->fancyWaterShader, "fullDepth");
     673    GLint tint = ogl_program_get_uniform_location(m->fancyWaterShader, "tint");
     674    GLint reflectionTint = ogl_program_get_uniform_location(m->fancyWaterShader, "reflectionTint");
     675    GLint reflectionTintStrength = ogl_program_get_uniform_location(m->fancyWaterShader, "reflectionTintStrength");
     676    GLint translation = ogl_program_get_uniform_location(m->fancyWaterShader, "translation");
     677    GLint repeatScale = ogl_program_get_uniform_location(m->fancyWaterShader, "repeatScale");
     678    GLint reflectionMatrix = ogl_program_get_uniform_location(m->fancyWaterShader, "reflectionMatrix");
     679    GLint refractionMatrix = ogl_program_get_uniform_location(m->fancyWaterShader, "refractionMatrix");
     680    GLint losMatrix = ogl_program_get_uniform_location(m->fancyWaterShader, "losMatrix");
     681    GLint normalMap = ogl_program_get_uniform_location(m->fancyWaterShader, "normalMap");
     682    GLint reflectionMap = ogl_program_get_uniform_location(m->fancyWaterShader, "reflectionMap");
     683    GLint refractionMap = ogl_program_get_uniform_location(m->fancyWaterShader, "refractionMap");
     684    GLint losMap = ogl_program_get_uniform_location(m->fancyWaterShader, "losMap");
     685
     686    const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
     687    pglUniform3fvARB(ambient, 1, &lightEnv.m_TerrainAmbientColor.X);
     688    pglUniform3fvARB(sunDir, 1, &lightEnv.GetSunDir().X);
     689    pglUniform3fvARB(sunColor, 1, &lightEnv.m_SunColor.X);
     690    pglUniform1fARB(shininess, WaterMgr->m_Shininess);
     691    pglUniform1fARB(specularStrength, WaterMgr->m_SpecularStrength);
     692    pglUniform1fARB(waviness, WaterMgr->m_Waviness);
     693    pglUniform1fARB(murkiness, WaterMgr->m_Murkiness);
     694    pglUniform1fARB(fullDepth, WaterMgr->m_WaterFullDepth);
     695    pglUniform3fvARB(tint, 1, WaterMgr->m_WaterTint.FloatArray());
     696    pglUniform1fARB(reflectionTintStrength, WaterMgr->m_ReflectionTintStrength);
     697    pglUniform3fvARB(reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray());
     698    pglUniform2fARB(translation, tx, ty);
     699    pglUniform1fARB(repeatScale, 1.0f / repeatPeriod);
     700    pglUniformMatrix4fvARB(reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11);
     701    pglUniformMatrix4fvARB(refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11);
     702    pglUniformMatrix4fvARB(losMatrix, 1, false, losTexture.GetTextureMatrix());
     703    pglUniform1iARB(normalMap, 0);      // texture unit 0
     704    pglUniform1iARB(reflectionMap, 1);  // texture unit 1
     705    pglUniform1iARB(refractionMap, 2);  // texture unit 2
     706    pglUniform1iARB(losMap, 3);         // texture unit 3
     707    pglUniform3fvARB(cameraPos, 1, &camPos.X);
     708
     709    glEnableClientState(GL_VERTEX_ARRAY);
     710    glEnableClientState(GL_COLOR_ARRAY);
     711
     712    for (size_t i = 0; i < m->visiblePatches.size(); ++i)
     713    {
     714        CPatchRData* data = m->visiblePatches[i];
     715        data->RenderWater();
     716    }
     717
     718    glDisableClientState(GL_COLOR_ARRAY);
     719    glDisableClientState(GL_VERTEX_ARRAY);
     720
     721    // Unbind the LOS/refraction/reflection textures and the shader
     722    g_Renderer.BindTexture(3, 0);
     723    g_Renderer.BindTexture(2, 0);
     724    g_Renderer.BindTexture(1, 0);
     725
     726    pglActiveTextureARB(GL_TEXTURE0_ARB);
     727
     728    ogl_program_use(0);
     729
     730    glDisable(GL_BLEND);
     731
     732    return true;
     733}
     734
     735void TerrainRenderer::RenderSimpleWater()
     736{
     737    PROFILE("render simple water");
     738
     739    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     740    CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
     741
     742    glEnable(GL_BLEND);
     743    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
     744    glEnable(GL_DEPTH_TEST);
     745    glDepthFunc(GL_LEQUAL);
     746
     747    double time = WaterMgr->m_WaterTexTimer;
     748    double period = 1.6f;
     749    int curTex = (int)(time*60/period) % 60;
     750
     751    WaterMgr->m_WaterTexture[curTex]->Bind();
     752
     753    // Shift the texture coordinates by these amounts to make the water "flow"
     754    float tx = -fmod(time, 81.0)/81.0;
     755    float ty = -fmod(time, 34.0)/34.0;
     756    float repeatPeriod = 16.0f;
     757
     758    // Perform the shifting by using texture coordinate generation
     759    GLfloat texgenS0[4] = { 1/repeatPeriod, 0, 0, tx };
     760    GLfloat texgenT0[4] = { 0, 0, 1/repeatPeriod, ty };
     761    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
     762    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
     763    glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS0);
     764    glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT0);
     765    glEnable(GL_TEXTURE_GEN_S);
     766    glEnable(GL_TEXTURE_GEN_T);
     767
     768    // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
     769    GLfloat waterColor[4] = { WaterMgr->m_WaterColor.r, WaterMgr->m_WaterColor.g, WaterMgr->m_WaterColor.b, 1.0f };
     770    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, waterColor);
     771    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     772    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     773    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
     774    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     775    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT);
     776    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
     777    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     778    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
     779    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
     780
     781    // Multiply by LOS texture
     782    losTexture.BindTexture(1);
     783    const float *losMatrix = losTexture.GetTextureMatrix();
     784    GLfloat texgenS1[4] = { losMatrix[0], losMatrix[4], losMatrix[8], losMatrix[12] };
     785    GLfloat texgenT1[4] = { losMatrix[1], losMatrix[5], losMatrix[9], losMatrix[13] };
     786    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
     787    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
     788    glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS1);
     789    glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT1);
     790    glEnable(GL_TEXTURE_GEN_S);
     791    glEnable(GL_TEXTURE_GEN_T);
     792
     793    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     794    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     795    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
     796    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     797    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
     798    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
     799    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     800    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
     801    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
     802
     803    // Set the proper LOD bias
     804    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
     805
     806    glEnableClientState(GL_VERTEX_ARRAY);
     807    glEnableClientState(GL_COLOR_ARRAY);
     808
     809    for (size_t i = 0; i < m->visiblePatches.size(); ++i)
     810    {
     811        CPatchRData* data = m->visiblePatches[i];
     812        data->RenderWater();
     813    }
     814
     815    glDisableClientState(GL_COLOR_ARRAY);
     816    glDisableClientState(GL_VERTEX_ARRAY);
     817
     818    g_Renderer.BindTexture(1, 0);
     819
     820    glDisable(GL_TEXTURE_GEN_S);
     821    glDisable(GL_TEXTURE_GEN_T);
     822    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
     823
     824    pglActiveTextureARB(GL_TEXTURE0_ARB);
     825
     826    // Clean up the texture matrix and blend mode
     827    glDisable(GL_TEXTURE_GEN_S);
     828    glDisable(GL_TEXTURE_GEN_T);
     829    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
     830
    769831    glDisable(GL_BLEND);
    770832    glDisable(GL_TEXTURE_2D);
    771833}
    772834
     835///////////////////////////////////////////////////////////////////
     836// Render water that is part of the terrain
     837void TerrainRenderer::RenderWater()
     838{
     839    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     840
     841    if (!WaterMgr->WillRenderFancyWater() || !RenderFancyWater())
     842        RenderSimpleWater();
     843}
     844
    773845void TerrainRenderer::RenderPriorities()
    774846{
  • ps/trunk/source/renderer/TerrainRenderer.h

    r9187 r9814  
    7373
    7474    /**
     75     * CullPatches: Culls patches and decals against a frustum,
     76     * and stores the results in a special filtered list that
     77     * is used when calling render functions with @p filtered true.
     78     */
     79    bool CullPatches(const CFrustum* frustum);
     80
     81    /**
    7582     * RenderTerrain: Render textured terrain (including blends between
    7683     * different terrain types).
     
    7885     * preconditions  : PrepareForRendering must have been called this
    7986     * frame before calling RenderTerrain.
     87     *
     88     * @param filtered If true then only render objects that passed CullPatches.
    8089     */
    81     void RenderTerrain();
     90    void RenderTerrain(bool filtered = false);
    8291
    8392    /**
     
    8695     *
    8796     * @param shadow A prepared shadow map, in case rendering with shadows is enabled.
     97     * @param filtered If true then only render objects that passed CullPatches.
    8898     */
    89     void RenderTerrainShader(ShadowMap* shadow);
     99    void RenderTerrainShader(ShadowMap* shadow, bool filtered = false);
    90100
    91101    /**
     
    94104     * preconditions  : PrepareForRendering must have been called this
    95105     * frame before calling RenderPatches.
     106     *
     107     * @param filtered If true then only render objects that passed CullPatches.
    96108     */
    97     void RenderPatches();
     109    void RenderPatches(bool filtered = false);
    98110
    99111    /**
     
    102114     * preconditions  : PrepareForRendering must have been called this
    103115     * frame before calling RenderOutlines.
     116     *
     117     * @param filtered If true then only render objects that passed CullPatches.
    104118     */
    105     void RenderOutlines();
     119    void RenderOutlines(bool filtered = false);
    106120
    107121    /**
     
    115129
    116130    /**
     131     * Calculate a scissor rectangle for the visible water patches.
     132     */
     133    CBound ScissorWater(const CMatrix3D& viewproj);
     134
     135    /**
    117136     * Render priority text for all submitted patches, for debugging.
    118137     */
     
    122141    TerrainRendererInternals* m;
    123142
     143    /**
     144     * RenderFancyWater: internal rendering method for fancy water.
     145     * Returns false if unable to render with fancy water.
     146     */
     147    bool RenderFancyWater();
     148
     149    /**
     150     * RenderSimpleWater: internal rendering method for water
     151     */
     152    void RenderSimpleWater();
     153
    124154    void PrepareShader(const CShaderProgramPtr& shader, ShadowMap* shadow);
    125155};
  • ps/trunk/source/renderer/TransparencyRenderer.cpp

    r9362 r9814  
    541541}
    542542
    543 
     543void SortModelRenderer::Filter(CModelFilter& filter, int passed, int flags)
     544{
     545    for (std::vector<SModel*>::iterator it = m->models.begin(); it != m->models.end(); ++it)
     546    {
     547        SModel* smdl = *it;
     548        CModel* mdl = smdl->GetModel();
     549        if (flags && !(mdl->GetFlags() & flags))
     550            continue;
     551
     552        if (filter.Filter(mdl))
     553            mdl->SetFlags(mdl->GetFlags() | passed);
     554        else
     555            mdl->SetFlags(mdl->GetFlags() & ~passed);
     556    }
     557}
    544558
    545559///////////////////////////////////////////////////////////////////////////////////////////////////
     
    556570int TransparentRenderModifier::BeginPass(int pass)
    557571{
     572    // First pass: opaque areas only.
     573    // Second pass: blended areas.
     574    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     575    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     576    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
     577    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     578    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
     579    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
     580
     581    // just pass through texture's alpha
     582    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     583    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
     584    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
     585
     586    // Set the proper LOD bias
     587    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
     588
     589    glEnable(GL_BLEND);
     590    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     591
     592    glEnable(GL_ALPHA_TEST);
    558593    if (pass == 0)
    559594    {
    560         // First pass: Put down Z for opaque parts of the model,
    561         // don't touch the color buffer.
    562 
    563         glDepthMask(1);
    564 
    565         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    566         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
    567         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT);
    568         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
    569 
    570         // just pass through texture's alpha
    571         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
    572         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
    573         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    574 
    575         // Set the proper LOD bias
    576         glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
    577 
    578         glEnable(GL_ALPHA_TEST);
    579         glAlphaFunc(GL_GREATER,0.975f);
    580 
    581         // render everything with color writes off to setup depth buffer correctly
    582         glColorMask(0,0,0,0);
    583 
    584         return STREAM_POS|STREAM_UV0;
     595        glAlphaFunc(GL_GREATER, 0.9375f);
    585596    }
    586597    else
    587598    {
    588         // Second pass: Put down color, disable Z write
    589         glColorMask(1,1,1,1);
    590 
     599        glAlphaFunc(GL_GREATER, 0.0f);
     600        glDepthFunc(GL_LESS);
    591601        glDepthMask(0);
    592 
    593         // setup texture environment to modulate diffuse color with texture color
    594         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
    595         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
    596         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
    597         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
    598         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
    599 
    600         glAlphaFunc(GL_GREATER,0);
    601 
    602         glEnable(GL_BLEND);
    603         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    604 
    605         // Set the proper LOD bias
    606         glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
    607 
    608         return STREAM_POS|STREAM_COLOR|STREAM_UV0;
    609     }
     602    }
     603
     604    return STREAM_POS|STREAM_COLOR|STREAM_UV0;
    610605}
    611606
    612607bool TransparentRenderModifier::EndPass(int pass)
    613608{
    614     if (pass == 0)
    615         return false; // multi-pass
    616 
    617609    glDisable(GL_BLEND);
    618610    glDisable(GL_ALPHA_TEST);
     611    if (pass == 0)
     612        return false;
     613
     614    glDepthFunc(GL_LEQUAL);
    619615    glDepthMask(1);
    620616
     
    632628}
    633629
     630
     631///////////////////////////////////////////////////////////////////////////////////////////////////
     632// TransparentOpaqueRenderModifier implementation
     633
     634TransparentOpaqueRenderModifier::TransparentOpaqueRenderModifier()
     635{
     636}
     637
     638TransparentOpaqueRenderModifier::~TransparentOpaqueRenderModifier()
     639{
     640}
     641
     642int TransparentOpaqueRenderModifier::BeginPass(int pass)
     643{
     644    ENSURE(pass == 0);
     645
     646    // Put down opaque parts of the model only.
     647
     648    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     649    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     650    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
     651    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     652    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
     653    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
     654
     655    // just pass through texture's alpha
     656    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     657    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
     658    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
     659
     660    // Set the proper LOD bias
     661    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
     662
     663    glEnable(GL_ALPHA_TEST);
     664    glAlphaFunc(GL_GREATER, 0.9375f);
     665
     666    glEnable(GL_BLEND);
     667    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     668
     669    return STREAM_POS|STREAM_COLOR|STREAM_UV0;
     670}
     671
     672bool TransparentOpaqueRenderModifier::EndPass(int UNUSED(pass))
     673{
     674    glDisable(GL_ALPHA_TEST);
     675    glDisable(GL_BLEND);
     676
     677    return true;
     678}
     679
     680void TransparentOpaqueRenderModifier::PrepareTexture(int UNUSED(pass), CTexturePtr& texture)
     681{
     682    texture->Bind(0);
     683}
     684
     685void TransparentOpaqueRenderModifier::PrepareModel(int UNUSED(pass), CModel* UNUSED(model))
     686{
     687    // No per-model setup necessary
     688}
     689
     690///////////////////////////////////////////////////////////////////////////////////////////////////
     691// TransparentBlendRenderModifier implementation
     692
     693TransparentBlendRenderModifier::TransparentBlendRenderModifier()
     694{
     695}
     696
     697TransparentBlendRenderModifier::~TransparentBlendRenderModifier()
     698{
     699}
     700
     701int TransparentBlendRenderModifier::BeginPass(int pass)
     702{
     703    ENSURE(pass == 0);
     704
     705    // Put down blended parts of the model only.
     706
     707    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     708    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     709    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
     710    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     711    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
     712    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
     713
     714    // just pass through texture's alpha
     715    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     716    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
     717    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
     718
     719    // Set the proper LOD bias
     720    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
     721
     722    glEnable(GL_ALPHA_TEST);
     723    glAlphaFunc(GL_GREATER,0);
     724
     725    glEnable(GL_BLEND);
     726    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     727
     728    glDepthFunc(GL_LESS);
     729    glDepthMask(0);
     730
     731    return STREAM_POS|STREAM_COLOR|STREAM_UV0;
     732}
     733
     734bool TransparentBlendRenderModifier::EndPass(int UNUSED(pass))
     735{
     736    glDisable(GL_ALPHA_TEST);
     737    glDisable(GL_BLEND);
     738    glDepthFunc(GL_LEQUAL);
     739    glDepthMask(1);
     740
     741    return true;
     742}
     743
     744void TransparentBlendRenderModifier::PrepareTexture(int UNUSED(pass), CTexturePtr& texture)
     745{
     746    texture->Bind(0);
     747}
     748
     749void TransparentBlendRenderModifier::PrepareModel(int UNUSED(pass), CModel* UNUSED(model))
     750{
     751    // No per-model setup necessary
     752}
    634753
    635754///////////////////////////////////////////////////////////////////////////////////////////////////
  • ps/trunk/source/renderer/TransparencyRenderer.h

    r9190 r9814  
    8686    bool HaveSubmissions();
    8787    void Render(const RenderModifierPtr& modifier, int flags);
     88    void Filter(CModelFilter& filter, int passed, int flags);
    8889
    8990private:
     
    107108    void PrepareTexture(int pass, CTexturePtr& texture);
    108109    void PrepareModel(int pass, CModel* model);
    109 
    110110};
    111111
     112/**
     113 * Class TransparentOpaqueRenderModifier: Modifier for transparent models,
     114 * including alpha blending and lighting, Opaque pass only.
     115 */
     116class TransparentOpaqueRenderModifier : public RenderModifier
     117{
     118public:
     119    TransparentOpaqueRenderModifier();
     120    ~TransparentOpaqueRenderModifier();
     121
     122    // Implementation
     123    int BeginPass(int pass);
     124    bool EndPass(int pass);
     125    void PrepareTexture(int pass, CTexturePtr& texture);
     126    void PrepareModel(int pass, CModel* model);
     127};
     128
     129/**
     130 * Class TransparentBlendRenderModifier: Modifier for transparent models,
     131 * including alpha blending and lighting. Blend pass only.
     132 */
     133class TransparentBlendRenderModifier : public RenderModifier
     134{
     135public:
     136    TransparentBlendRenderModifier();
     137    ~TransparentBlendRenderModifier();
     138
     139    // Implementation
     140    int BeginPass(int pass);
     141    bool EndPass(int pass);
     142    void PrepareTexture(int pass, CTexturePtr& texture);
     143    void PrepareModel(int pass, CModel* model);
     144};
    112145
    113146/**
Note: See TracChangeset for help on using the changeset viewer.