diff --git a/components/nifogre/material.cpp b/components/nifogre/material.cpp index 55f064c55..8398dbc2e 100644 --- a/components/nifogre/material.cpp +++ b/components/nifogre/material.cpp @@ -334,6 +334,10 @@ Ogre::String NIFMaterialLoader::getMaterial(const Nif::ShapeData *shapedata, instance->setProperty("detailMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::DetailTexture].uvSet))); } + bool useParallax = !texName[Nif::NiTexturingProperty::BumpTexture].empty() + && texName[Nif::NiTexturingProperty::BumpTexture].find("_nh.") != std::string::npos; + instance->setProperty("use_parallax", sh::makeProperty(new sh::BooleanValue(useParallax))); + for(int i = 0;i < 7;i++) { if(i == Nif::NiTexturingProperty::BaseTexture || diff --git a/files/materials/core.h b/files/materials/core.h index 6f8179c08..a912e2356 100644 --- a/files/materials/core.h +++ b/files/materials/core.h @@ -91,7 +91,7 @@ precision mediump float; #define shSamplerCube(name) uniform samplerCube name; @shUseSampler(name) - #define shMatrixMult(m, v) (m * v) + #define shMatrixMult(m, v) ((m) * (v)) #define shOutputPosition gl_Position diff --git a/files/materials/objects.mat b/files/materials/objects.mat index ffba6e7ea..32787e159 100644 --- a/files/materials/objects.mat +++ b/files/materials/objects.mat @@ -12,6 +12,7 @@ material openmw_objects_base use_detail_map false emissiveMapUVSet 0 detailMapUVSet 0 + use_parallax false scene_blend default depth_write default @@ -37,6 +38,7 @@ material openmw_objects_base detailMap $detailMap env_map $env_map env_map_color $env_map_color + use_parallax $use_parallax } diffuse $diffuse diff --git a/files/materials/objects.shader b/files/materials/objects.shader index fb2b30426..5a3d872a5 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -18,6 +18,10 @@ #define EMISSIVE_MAP @shPropertyHasValue(emissiveMap) #define DETAIL_MAP @shPropertyHasValue(detailMap) +#define PARALLAX @shPropertyBool(use_parallax) +#define PARALLAX_SCALE 0.04 +#define PARALLAX_BIAS -0.02 + // right now we support 2 UV sets max. implementing them is tedious, and we're probably not going to need more #define SECOND_UV_SET (@shPropertyString(emissiveMapUVSet) || @shPropertyString(detailMapUVSet)) @@ -265,7 +269,7 @@ shUniform(float3, env_map_color) @shUniformProperty3f(env_map_color, env_map_color) #endif -#if ENV_MAP || SPECULAR +#if ENV_MAP || SPECULAR || PARALLAX shUniform(float3, cameraPosObjSpace) @shAutoConstant(cameraPosObjSpace, camera_position_object_space) #endif #if SPECULAR @@ -345,21 +349,12 @@ SH_START_PROGRAM { + float4 newUV = UV; + #ifdef NEED_DEPTH float depthPassthrough = objSpacePositionPassthrough.w; #endif - float4 diffuse = shSample(diffuseMap, UV.xy); - shOutputColour(0) = diffuse; - -#if DETAIL_MAP -#if @shPropertyString(detailMapUVSet) - shOutputColour(0) *= shSample(detailMap, UV.zw)*2; -#else - shOutputColour(0) *= shSample(detailMap, UV.xy)*2; -#endif -#endif - #if NEED_NORMAL float3 normal = normalPassthrough; #endif @@ -372,10 +367,32 @@ tbn = transpose(tbn); #endif - float3 TSnormal = shSample(normalMap, UV.xy).xyz * 2 - 1; + float4 normalTex = shSample(normalMap, UV.xy); + + normal = normalize (shMatrixMult( transpose(tbn), normalTex.xyz * 2 - 1 )); +#endif + +#if ENV_MAP || SPECULAR || PARALLAX + float3 eyeDir = normalize(cameraPosObjSpace.xyz - objSpacePositionPassthrough.xyz); +#endif + +#if PARALLAX + float3 TSeyeDir = normalize(shMatrixMult(tbn, eyeDir)); + + newUV += (TSeyeDir.xyxy * ( normalTex.a * PARALLAX_SCALE + PARALLAX_BIAS )).xyxy; +#endif - normal = normalize (shMatrixMult( transpose(tbn), TSnormal )); + float4 diffuse = shSample(diffuseMap, newUV.xy); + shOutputColour(0) = diffuse; + +#if DETAIL_MAP +#if @shPropertyString(detailMapUVSet) + shOutputColour(0) *= shSample(detailMap, newUV.zw)*2; +#else + shOutputColour(0) *= shSample(detailMap, newUV.xy)*2; #endif +#endif + #if !VERTEX_LIGHTING float3 viewPos = shMatrixMult(worldView, float4(objSpacePositionPassthrough.xyz,1)).xyz; @@ -458,16 +475,12 @@ #if EMISSIVE_MAP #if @shPropertyString(emissiveMapUVSet) - shOutputColour(0).xyz += shSample(emissiveMap, UV.zw).xyz; + shOutputColour(0).xyz += shSample(emissiveMap, newUV.zw).xyz; #else - shOutputColour(0).xyz += shSample(emissiveMap, UV.xy).xyz; + shOutputColour(0).xyz += shSample(emissiveMap, newUV.xy).xyz; #endif #endif -#if ENV_MAP || SPECULAR - float3 eyeDir = normalize(cameraPosObjSpace.xyz - objSpacePositionPassthrough.xyz); -#endif - #if ENV_MAP // Everything looks better with fresnel float facing = 1.0 - max(abs(dot(-eyeDir, normal)), 0);