From 15a16aeba1c2b7fd0ba3e47b14fd673a17295524 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Wed, 1 Aug 2012 04:11:16 +0200
Subject: [PATCH] Fixed DirectX HLSL shaders and re-enabled them in the gui

---
 apps/openmw/mwgui/settingswindow.cpp      | 12 ++++------
 apps/openmw/mwrender/renderingmanager.cpp | 16 ++++++-------
 files/materials/core.h                    | 29 +++++++++++++----------
 files/materials/objects.shaderset         |  4 ++--
 files/materials/terrain.shaderset         |  4 ++--
 files/materials/underwater.h              | 10 ++++----
 files/materials/water.shader              | 11 +++++----
 files/materials/water.shaderset           |  4 ++--
 8 files changed, 46 insertions(+), 44 deletions(-)

diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp
index d8b0c96d7..4488096fe 100644
--- a/apps/openmw/mwgui/settingswindow.cpp
+++ b/apps/openmw/mwgui/settingswindow.cpp
@@ -75,9 +75,9 @@ namespace
         return boost::lexical_cast<std::string>(xaspect) + " : " + boost::lexical_cast<std::string>(yaspect);
     }
 
-    bool hasGLSL ()
+    std::string hlslGlsl ()
     {
-        return (Ogre::Root::getSingleton ().getRenderSystem ()->getName ().find("OpenGL") != std::string::npos);
+        return (Ogre::Root::getSingleton ().getRenderSystem ()->getName ().find("OpenGL") != std::string::npos) ? "glsl" : "hlsl";
     }
 }
 
@@ -393,12 +393,9 @@ namespace MWGui
         std::string val = static_cast<MyGUI::Button*>(_sender)->getCaption();
         if (val == "off")
         {
-            if (hasGLSL ())
-                val = "glsl";
-            else
-                val = "cg";
+            val = hlslGlsl();
         }
-        else if (val == "glsl")
+        else if (val == hlslGlsl())
             val = "cg";
         else
             val = "off";
@@ -411,6 +408,7 @@ namespace MWGui
 
             // water shader not supported with object shaders off
             mWaterShaderButton->setCaptionWithReplacing("#{sOff}");
+            mUnderwaterButton->setCaptionWithReplacing("#{sOff}");
             mWaterShaderButton->setEnabled(false);
             mReflectObjectsButton->setEnabled(false);
             mReflectActorsButton->setEnabled(false);
diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp
index ae0e57219..a4b2e8489 100644
--- a/apps/openmw/mwrender/renderingmanager.cpp
+++ b/apps/openmw/mwrender/renderingmanager.cpp
@@ -43,12 +43,14 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
     :mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0)
 {
     // select best shader mode
-    if (Settings::Manager::getString("shader mode", "General") == "")
+    bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos);
+
+    // glsl is only supported in opengl mode and hlsl only in direct3d mode.
+    if (Settings::Manager::getString("shader mode", "General") == ""
+            || (openGL && Settings::Manager::getString("shader mode", "General") == "hlsl")
+            || (!openGL && Settings::Manager::getString("shader mode", "General") == "glsl"))
     {
-        if (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") == std::string::npos)
-            Settings::Manager::setString("shader mode", "General", "cg");
-        else
-            Settings::Manager::setString("shader mode", "General", "glsl");
+        Settings::Manager::setString("shader mode", "General", openGL ? "glsl" : "hlsl");
     }
 
     mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
@@ -74,10 +76,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
     mFactory->setCurrentLanguage (lang);
     mFactory->loadAllFiles();
 
-    //The fog type must be set before any terrain objects are created as if the
-    //fog type is set to FOG_NONE then the initially created terrain won't have any fog
-    configureFog(1, ColourValue(1,1,1));
-
     // Set default mipmap level (NB some APIs ignore this)
     TextureManager::getSingleton().setDefaultNumMipmaps(Settings::Manager::getInt("num mipmaps", "General"));
 
diff --git a/files/materials/core.h b/files/materials/core.h
index 6e27d349c..cba716777 100644
--- a/files/materials/core.h
+++ b/files/materials/core.h
@@ -1,20 +1,20 @@
-#if SH_HLSL == 1
-    #error "HLSL is unsupported"
-#endif
-
-#if SH_CG == 1
+#if SH_HLSL == 1 || SH_CG == 1
 
     #define shTexture2D sampler2D
     #define shSample(tex, coord) tex2D(tex, coord)
+    #define shCubicSample(tex, coord) texCUBE(tex, coord)
     #define shLerp(a, b, t) lerp(a, b, t)
     #define shSaturate(a) saturate(a)
 
     #define shSampler2D(name) , uniform sampler2D name : register(s@shCounter(0)) @shUseSampler(name)
+    
+    #define shSamplerCube(name) , uniform samplerCUBE name : register(s@shCounter(0)) @shUseSampler(name)
 
     #define shMatrixMult(m, v) mul(m, v)
 
     #define shUniform(type, name) , uniform type name
 
+    #define shTangentInput(type) , in type tangent : TANGENT
     #define shVertexInput(type, name) , in type name : TEXCOORD@shCounter(1)
     #define shInput(type, name) , in type name : TEXCOORD@shCounter(1)
     #define shOutput(type, name) , out type name : TEXCOORD@shCounter(2)
@@ -65,9 +65,10 @@
     #define float4 vec4
     #define int2 ivec2
     #define int3 ivec3
-    #define int4 ivec4/
+    #define int4 ivec4
     #define shTexture2D sampler2D
     #define shSample(tex, coord) texture2D(tex, coord)
+    #define shCubicSample(tex, coord) textureCube(tex, coord)
     #define shLerp(a, b, t) mix(a, b, t)
     #define shSaturate(a) clamp(a, 0.0, 1.0)
 
@@ -75,11 +76,14 @@
 
     #define shSampler2D(name) uniform sampler2D name; @shUseSampler(name)
 
+    #define shSamplerCube(name) uniform samplerCube name; @shUseSampler(name)
+
     #define shMatrixMult(m, v) (m * v)
 
     #define shOutputPosition gl_Position
 
     #define float4x4 mat4
+    #define float3x3 mat3
     
     // GLSL 1.3
     #if 0
@@ -89,8 +93,8 @@
 
     #define shOutputColour(num) oColor##num
 
-
-
+    #define shTangentInput(type) in type tangent;
+    #define shVertexInput(type, name) in type name;
     #define shInput(type, name) in type name;
     #define shOutput(type, name) out type name;
 
@@ -101,7 +105,7 @@
     #ifdef SH_VERTEX_SHADER
 
         #define SH_BEGIN_PROGRAM \
-            in float4 shInputPosition;
+            in float4 vertex;
         #define SH_START_PROGRAM \
             void main(void)
 
@@ -126,10 +130,11 @@
     #if 1
     
     // automatically recognized by ogre when the input name equals this
-    #define shInputPosition gl_Vertex
+    #define shInputPosition vertex
 
     #define shOutputColour(num) gl_FragData[num]
 
+    #define shTangentInput(type) attribute type tangent;
     #define shVertexInput(type, name) attribute type name;
     #define shInput(type, name) varying type name;
     #define shOutput(type, name) varying type name;
@@ -140,8 +145,8 @@
 
     #ifdef SH_VERTEX_SHADER
 
-        #define SH_BEGIN_PROGRAM 
-
+        #define SH_BEGIN_PROGRAM \
+            attribute vec4 vertex; 
         #define SH_START_PROGRAM \
             void main(void)
 
diff --git a/files/materials/objects.shaderset b/files/materials/objects.shaderset
index ccb975fe9..028c15ce8 100644
--- a/files/materials/objects.shaderset
+++ b/files/materials/objects.shaderset
@@ -3,7 +3,7 @@ shader_set openmw_objects_vertex
     source objects.shader
     type vertex
     profiles_cg vs_2_0 vp40 arbvp1
-    profiles_hlsl vs_2_0
+    profiles_hlsl vs_3_0 vs_2_0
 }
 
 shader_set openmw_objects_fragment
@@ -11,5 +11,5 @@ shader_set openmw_objects_fragment
     source objects.shader
     type fragment
     profiles_cg ps_3_0 ps_2_x ps_2_0 fp40 arbfp1
-    profiles_hlsl ps_2_0
+    profiles_hlsl ps_3_0 ps_2_0
 }
diff --git a/files/materials/terrain.shaderset b/files/materials/terrain.shaderset
index be8ecd7d8..a72f2358f 100644
--- a/files/materials/terrain.shaderset
+++ b/files/materials/terrain.shaderset
@@ -3,7 +3,7 @@ shader_set terrain_vertex
     source terrain.shader
     type vertex
     profiles_cg vs_2_0 vp40 arbvp1
-    profiles_hlsl vs_2_0
+    profiles_hlsl vs_3_0 vs_2_0
 }
 
 shader_set terrain_fragment
@@ -11,5 +11,5 @@ shader_set terrain_fragment
     source terrain.shader
     type fragment
     profiles_cg ps_3_0 ps_2_x ps_2_0 fp40 arbfp1
-    profiles_hlsl ps_2_0
+    profiles_hlsl ps_3_0 ps_2_0
 }
diff --git a/files/materials/underwater.h b/files/materials/underwater.h
index fe19ff93b..18052a98d 100644
--- a/files/materials/underwater.h
+++ b/files/materials/underwater.h
@@ -28,7 +28,7 @@ float3 intercept(float3 lineP,
 
 float3 perturb1(shTexture2D tex, float2 coords, float bend, float2 windDir, float windSpeed, float timer)
 {
-    float2 nCoord = float2(0.0);
+    float2 nCoord = float2(0,0);
     bend *= WAVE_CHOPPYNESS;
   	nCoord = coords * (WAVE_SCALE * 0.05) + windDir * timer * (windSpeed*0.04);
     float3 normal0 = 2.0 * shSample(tex, nCoord + float2(-timer*0.015,-timer*0.05)).rgb - 1.0;
@@ -55,8 +55,8 @@ float3 perturb1(shTexture2D tex, float2 coords, float bend, float2 windDir, floa
 float3 perturb(shTexture2D tex, float2 coords, float bend, float2 windDir, float windSpeed, float timer)
 {
     bend *= WAVE_CHOPPYNESS;
-    float3 col = float3(0.0);
-    float2 nCoord = float2(0.0); //normal coords
+    float3 col = float3(0,0,0);
+    float2 nCoord = float2(0,0); //normal coords
 
     nCoord = coords * (WAVE_SCALE * 0.025) + windDir * timer * (windSpeed*0.03);
     col += shSample(tex,nCoord + float2(-timer*0.005,-timer*0.01)).rgb*0.20;
@@ -102,11 +102,11 @@ float3 getCaustics (shTexture2D causticMap, float3 worldPos, float3 waterEyePos,
     /// \todo sunFade
     
    // float3 caustics = clamp(pow(float3(causticR)*5.5,float3(5.5*causticdepth)),0.0,1.0)*NdotL*sunFade*causticdepth;
-    float3 caustics = clamp(pow(float3(causticR)*5.5,float3(5.5*causticdepth)),0.0,1.0)*NdotL*causticdepth;
+    float3 caustics = clamp(pow(float3(causticR,causticR,causticR)*5.5,float3(5.5*causticdepth,5.5*causticdepth,5.5*causticdepth)),0.0,1.0)*NdotL*causticdepth;
     float causticG = 1.0-perturb(causticMap,causticPos.xz+(1.0-causticdepth)*ABBERATION, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z;
     float causticB = 1.0-perturb(causticMap,causticPos.xz+(1.0-causticdepth)*ABBERATION*2.0, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z;
     //caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth)))*NdotL*sunFade*causticdepth;
-                caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth)))*NdotL*causticdepth;
+                caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth,5.5*causticdepth,5.5*causticdepth)))*NdotL*causticdepth;
 
     caustics *= 3;
     
diff --git a/files/materials/water.shader b/files/materials/water.shader
index 2145919b0..08a19ace9 100644
--- a/files/materials/water.shader
+++ b/files/materials/water.shader
@@ -198,7 +198,7 @@
         float depth = shSample(depthMap, screenCoords).x * far - depthPassthrough;
         float shoreFade = shSaturate(depth / 50.0);
 
-	    float2 nCoord = float2(0.0);
+	    float2 nCoord = float2(0,0);
 
       	nCoord = UV * (WAVE_SCALE * 0.05) + WIND_DIR * waterTimer * (WIND_SPEED*0.04);
 	    float3 normal0 = 2.0 * shSample(normalMap, nCoord + float2(-waterTimer*0.015,-waterTimer*0.005)).rgb - 1.0;
@@ -238,12 +238,12 @@
         
         // sunlight scattering
         float3 pNormal = float3(0,1,0);
-    	vec3 lR = reflect(lVec, lNormal);
-        vec3 llR = reflect(lVec, pNormal);
+    	float3 lR = reflect(lVec, lNormal);
+        float3 llR = reflect(lVec, pNormal);
         
         float s = shSaturate(dot(lR, vVec)*2.0-1.2);
         float lightScatter = shSaturate(dot(-lVec,lNormal)*0.7+0.3) * s * SCATTER_AMOUNT * waterSunFade_sunHeight.x * shSaturate(1.0-exp(-waterSunFade_sunHeight.y));
-        float3 scatterColour = shLerp(vec3(SCATTER_COLOUR)*vec3(1.0,0.4,0.0), SCATTER_COLOUR, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT)));
+        float3 scatterColour = shLerp(float3(SCATTER_COLOUR)*float3(1.0,0.4,0.0), SCATTER_COLOUR, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT)));
 
         // fresnel
         float ior = (cameraPos.y>0)?(1.333/1.0):(1.0/1.333); //air to water; water to air
@@ -284,7 +284,7 @@
             waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0);
             float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0;
             float3 waterext = float3(0.6, 0.9, 1.0);//water extinction
-            watercolour = mix(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT)));
+            watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT)));
         
             float darkness = VISIBILITY*2.0;
             darkness = clamp((cameraPos.y+darkness)/darkness,0.2,1.0);
@@ -299,6 +299,7 @@
             shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue);
         }
 
+		shOutputColour(0).w = 1;
     }
 
 #endif
diff --git a/files/materials/water.shaderset b/files/materials/water.shaderset
index 754ac8e49..5e070a45a 100644
--- a/files/materials/water.shaderset
+++ b/files/materials/water.shaderset
@@ -3,7 +3,7 @@ shader_set water_vertex
     source water.shader
     type vertex
     profiles_cg vs_2_0 vp40 arbvp1
-    profiles_hlsl vs_2_0
+    profiles_hlsl vs_3_0 vs_2_0
 }
 
 shader_set water_fragment
@@ -11,5 +11,5 @@ shader_set water_fragment
     source water.shader
     type fragment
     profiles_cg ps_2_x ps_2_0 ps fp40 arbfp1
-    profiles_hlsl ps_2_0
+    profiles_hlsl ps_3_0 ps_2_0
 }