mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-09-22 19:39:32 -04:00
flowmaps
This commit is contained in:
parent
1dbd5fd571
commit
42c8a5d5db
@ -200,33 +200,6 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleExtraData(const std::string& data, osg::Group* node)
|
|
||||||
{
|
|
||||||
YAML::Node root = YAML::Load(data);
|
|
||||||
|
|
||||||
for (const auto& it : root["shader"])
|
|
||||||
{
|
|
||||||
std::string key = it.first.as<std::string>();
|
|
||||||
|
|
||||||
if (key == "soft_effect" && NifOsg::Loader::getSoftEffectEnabled())
|
|
||||||
{
|
|
||||||
SceneUtil::SoftEffectConfig config;
|
|
||||||
config.mSize = it.second["size"].as<float>(config.mSize);
|
|
||||||
config.mFalloff = it.second["falloff"].as<bool>(config.mFalloff);
|
|
||||||
config.mFalloffDepth = it.second["falloffDepth"].as<float>(config.mFalloffDepth);
|
|
||||||
|
|
||||||
SceneUtil::setupSoftEffect(*node, config);
|
|
||||||
}
|
|
||||||
else if (key == "distortion")
|
|
||||||
{
|
|
||||||
SceneUtil::DistortionConfig config;
|
|
||||||
config.mStrength = it.second["strength"].as<float>(config.mStrength);
|
|
||||||
|
|
||||||
SceneUtil::setupDistortion(*node, config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace NifOsg
|
namespace NifOsg
|
||||||
@ -664,6 +637,64 @@ namespace NifOsg
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleExtraData(
|
||||||
|
const Nif::NiAVObject* nifNode, const std::string& data, osg::Group* node, HandleNodeArgs& args)
|
||||||
|
{
|
||||||
|
YAML::Node root = YAML::Load(data);
|
||||||
|
|
||||||
|
const bool isNiGeometry = isTypeNiGeometry(nifNode->recType);
|
||||||
|
const bool isBSGeometry = isTypeBSGeometry(nifNode->recType);
|
||||||
|
const bool isGeometry = isNiGeometry || isBSGeometry;
|
||||||
|
|
||||||
|
for (const auto& it : root["shader"])
|
||||||
|
{
|
||||||
|
std::string key = it.first.as<std::string>();
|
||||||
|
|
||||||
|
if (key == "soft_effect" && NifOsg::Loader::getSoftEffectEnabled())
|
||||||
|
{
|
||||||
|
SceneUtil::SoftEffectConfig config;
|
||||||
|
config.mSize = it.second["size"].as<float>(config.mSize);
|
||||||
|
config.mFalloff = it.second["falloff"].as<bool>(config.mFalloff);
|
||||||
|
config.mFalloffDepth = it.second["falloffDepth"].as<float>(config.mFalloffDepth);
|
||||||
|
|
||||||
|
SceneUtil::setupSoftEffect(*node, config);
|
||||||
|
}
|
||||||
|
else if (key == "distortion")
|
||||||
|
{
|
||||||
|
SceneUtil::DistortionConfig config;
|
||||||
|
config.mStrength = it.second["strength"].as<float>(config.mStrength);
|
||||||
|
|
||||||
|
SceneUtil::setupDistortion(*node, config);
|
||||||
|
}
|
||||||
|
else if (key == "flowmap")
|
||||||
|
{
|
||||||
|
if (!isGeometry)
|
||||||
|
{
|
||||||
|
throw Nif::Exception(
|
||||||
|
"flowmap effect can only be used on geometry nodes such as NiTriShape", mFilename.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneUtil::FlowMapConfig config;
|
||||||
|
config.mStrength = it.second["strength"].as<float>(config.mStrength);
|
||||||
|
config.mSpeed = it.second["speed"].as<float>(config.mSpeed);
|
||||||
|
config.mOffset = it.second["offset"].as<float>(config.mOffset);
|
||||||
|
config.mJump = it.second["jump"].as<osg::Vec2f>(config.mJump);
|
||||||
|
|
||||||
|
std::string path = it.second["texture"]["path"].as<std::string>();
|
||||||
|
int uvSet = it.second["texture"]["uvSet"].as<int>(0);
|
||||||
|
|
||||||
|
config.mTexture = new osg::Texture2D(getTextureImage(path));
|
||||||
|
config.mTexture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
|
||||||
|
config.mTexture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
|
||||||
|
config.mTextureUnit = args.mBoundTextures.size();
|
||||||
|
|
||||||
|
args.mBoundTextures.emplace_back(uvSet);
|
||||||
|
|
||||||
|
SceneUtil::setupFlowMap(*node, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> handleNode(
|
osg::ref_ptr<osg::Node> handleNode(
|
||||||
const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode, HandleNodeArgs args)
|
const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode, HandleNodeArgs args)
|
||||||
{
|
{
|
||||||
@ -830,7 +861,7 @@ namespace NifOsg
|
|||||||
|
|
||||||
// Apply any extra effects after processing the nodes children and particle system handling
|
// Apply any extra effects after processing the nodes children and particle system handling
|
||||||
if (!extraData.empty())
|
if (!extraData.empty())
|
||||||
handleExtraData(extraData, node);
|
handleExtraData(nifNode, extraData, node, args);
|
||||||
|
|
||||||
if (composite->getNumControllers() > 0)
|
if (composite->getNumControllers() > 0)
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#include "extradata.hpp"
|
#include "extradata.hpp"
|
||||||
|
|
||||||
#include <osg/Node>
|
#include <osg/Node>
|
||||||
|
#include <osg/Vec2f>
|
||||||
|
|
||||||
#include <components/misc/osguservalues.hpp>
|
#include <components/misc/osguservalues.hpp>
|
||||||
#include <components/sceneutil/depth.hpp>
|
#include <components/sceneutil/depth.hpp>
|
||||||
|
#include <components/sceneutil/texturetype.hpp>
|
||||||
|
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
@ -35,4 +37,18 @@ namespace SceneUtil
|
|||||||
|
|
||||||
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setupFlowMap(osg::Node& node, const FlowMapConfig& config)
|
||||||
|
{
|
||||||
|
osg::StateSet* stateset = node.getOrCreateStateSet();
|
||||||
|
|
||||||
|
stateset->addUniform(new osg::Uniform("flowMapStrength", config.mStrength));
|
||||||
|
stateset->addUniform(new osg::Uniform("flowMapSpeed", config.mSpeed));
|
||||||
|
stateset->addUniform(new osg::Uniform("flowMapOffset", config.mOffset));
|
||||||
|
stateset->addUniform(new osg::Uniform("flowMapJump", config.mJump));
|
||||||
|
|
||||||
|
stateset->setTextureAttribute(config.mTextureUnit, config.mTexture, osg::StateAttribute::ON);
|
||||||
|
stateset->setTextureAttribute(
|
||||||
|
config.mTextureUnit, new SceneUtil::TextureType("flowMap"), osg::StateAttribute::ON);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Node;
|
class Node;
|
||||||
|
class vec2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
@ -20,8 +21,19 @@ namespace SceneUtil
|
|||||||
float mStrength = 0.1f;
|
float mStrength = 0.1f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FlowMapConfig
|
||||||
|
{
|
||||||
|
float mStrength = 1.f;
|
||||||
|
float mSpeed = 1.f;
|
||||||
|
float mOffset = 0.f;
|
||||||
|
osg::Vec2f mJump = { 0.f, 0.f };
|
||||||
|
osg::ref_ptr<osg::Texture2D> mTexture = nullptr;
|
||||||
|
std::size_t mTextureUnit = 0;
|
||||||
|
};
|
||||||
|
|
||||||
void setupSoftEffect(osg::Node& node, const SoftEffectConfig& config);
|
void setupSoftEffect(osg::Node& node, const SoftEffectConfig& config);
|
||||||
void setupDistortion(osg::Node& node, const DistortionConfig& config);
|
void setupDistortion(osg::Node& node, const DistortionConfig& config);
|
||||||
|
void setupFlowMap(osg::Node& node, const FlowMapConfig& config);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -291,7 +291,7 @@ namespace Shader
|
|||||||
// shader defines. Normal maps and normal height maps both get sent to the shader as a normal map, so the latter
|
// shader defines. Normal maps and normal height maps both get sent to the shader as a normal map, so the latter
|
||||||
// must be detected separately.
|
// must be detected separately.
|
||||||
const char* defaultTextures[] = { "diffuseMap", "normalMap", "emissiveMap", "darkMap", "detailMap", "envMap",
|
const char* defaultTextures[] = { "diffuseMap", "normalMap", "emissiveMap", "darkMap", "detailMap", "envMap",
|
||||||
"specularMap", "decalMap", "bumpMap", "glossMap" };
|
"specularMap", "decalMap", "bumpMap", "glossMap", "flowMap" };
|
||||||
bool isTextureNameRecognized(std::string_view name)
|
bool isTextureNameRecognized(std::string_view name)
|
||||||
{
|
{
|
||||||
if (std::find(std::begin(defaultTextures), std::end(defaultTextures), name) != std::end(defaultTextures))
|
if (std::find(std::begin(defaultTextures), std::end(defaultTextures), name) != std::end(defaultTextures))
|
||||||
@ -395,6 +395,10 @@ namespace Shader
|
|||||||
// As well as gloss maps
|
// As well as gloss maps
|
||||||
writableStateSet->setTextureMode(unit, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
writableStateSet->setTextureMode(unit, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
else if (texName == "flowMap")
|
||||||
|
{
|
||||||
|
mRequirements.back().mShaderRequired = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Log(Debug::Error) << "ShaderVisitor encountered unknown texture " << texture;
|
Log(Debug::Error) << "ShaderVisitor encountered unknown texture " << texture;
|
||||||
|
@ -59,7 +59,7 @@ Distortion
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
This effect is used to imitate effects such as refraction and heat distortion. A common use case is to assign a normal map to the
|
This effect is used to imitate effects such as refraction and heat distortion. A common use case is to assign a normal map to the
|
||||||
diffuse slot to a material and add uv scrolling. The red and green channels of the texture are used to offset the final scene texture.
|
diffuse slot to a material and add UV scrolling. The red and green channels of the texture are used to offset the final scene texture.
|
||||||
Blue and alpha channels are ignored.
|
Blue and alpha channels are ignored.
|
||||||
|
|
||||||
To use this feature the :ref:`post processing <Post Processing>` setting must be enabled.
|
To use this feature the :ref:`post processing <Post Processing>` setting must be enabled.
|
||||||
@ -90,3 +90,64 @@ Example usage.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Flow Map
|
||||||
|
--------
|
||||||
|
|
||||||
|
+-----------------+
|
||||||
|
| Supported Nodes |
|
||||||
|
+-----------------+
|
||||||
|
| NiTriShape |
|
||||||
|
+-----------------+
|
||||||
|
| NiTriStrips |
|
||||||
|
+-----------------+
|
||||||
|
|
||||||
|
This effect allows textured geometry to be animated and distorted using flow map textures. This can be useful for simulating
|
||||||
|
flowing liquids or magical effects. UV maps are distorted according to the flow map texture. They are then blended with
|
||||||
|
another phase of the same UV at a different time offset. Flow maps can only be applied to geometry nodes, such as `NiTriShape`,
|
||||||
|
and affects the diffuse, normal, and specular maps.
|
||||||
|
|
||||||
|
Variables.
|
||||||
|
|
||||||
|
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+
|
||||||
|
| Name | Description | Type | Default |
|
||||||
|
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+
|
||||||
|
| strength| The strength of the flow map UV distortion. Scales linearly. | float | 1 |
|
||||||
|
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+
|
||||||
|
| speed | The speed of the flow map, affects both the UV distortion and the phase change. | float | 1 |
|
||||||
|
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+
|
||||||
|
| offset | The time offset of the flow map. Controls where the animation starts. | float | 0 |
|
||||||
|
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+
|
||||||
|
| jump | Controls the UV offset applied with each phase shift, along the x and y axis. | vec2f | [0, 0] |
|
||||||
|
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+
|
||||||
|
|
||||||
|
The flow map requires a texture and UV set to use. The red and green channels of the flow map texture are the flow directions
|
||||||
|
in x and y respectively, the blue channel is used to offset the phase change, hiding repetition. The texture path and UV set
|
||||||
|
are defined in a JSON object with the name `texture`.
|
||||||
|
|
||||||
|
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+
|
||||||
|
| Name | Description | Type | Default |
|
||||||
|
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+
|
||||||
|
| path | Path to the flow map texture in the VFS. This is required. | string | nullptr |
|
||||||
|
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+
|
||||||
|
| uvSet | ID of the UV set to use for the flow map texture. | int | 0 |
|
||||||
|
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+
|
||||||
|
|
||||||
|
Example usage.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
omw:data {
|
||||||
|
"shader" : {
|
||||||
|
"flowmap" : {
|
||||||
|
"strength": 0.5,
|
||||||
|
"speed": 1.0,
|
||||||
|
"offset": 0.0,
|
||||||
|
"jump": [0.25, 0.24],
|
||||||
|
"texture": {
|
||||||
|
"path" : "flowmap.tga",
|
||||||
|
"uvSet": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ set(SHADER_FILES
|
|||||||
lib/util/quickstep.glsl
|
lib/util/quickstep.glsl
|
||||||
lib/util/coordinates.glsl
|
lib/util/coordinates.glsl
|
||||||
lib/util/distortion.glsl
|
lib/util/distortion.glsl
|
||||||
|
lib/util/flowmap.glsl
|
||||||
lib/core/fragment.glsl
|
lib/core/fragment.glsl
|
||||||
lib/core/fragment.h.glsl
|
lib/core/fragment.h.glsl
|
||||||
lib/core/fragment_multiview.glsl
|
lib/core/fragment_multiview.glsl
|
||||||
|
@ -62,6 +62,11 @@ uniform sampler2D glossMap;
|
|||||||
varying vec2 glossMapUV;
|
varying vec2 glossMapUV;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if @flowMap
|
||||||
|
uniform sampler2D flowMap;
|
||||||
|
varying vec2 flowMapUV;
|
||||||
|
#endif
|
||||||
|
|
||||||
uniform vec2 screenRes;
|
uniform vec2 screenRes;
|
||||||
uniform float near;
|
uniform float near;
|
||||||
uniform float far;
|
uniform float far;
|
||||||
@ -94,6 +99,7 @@ varying vec4 passTangent;
|
|||||||
#include "lib/material/parallax.glsl"
|
#include "lib/material/parallax.glsl"
|
||||||
#include "lib/material/alpha.glsl"
|
#include "lib/material/alpha.glsl"
|
||||||
#include "lib/util/distortion.glsl"
|
#include "lib/util/distortion.glsl"
|
||||||
|
#include "lib/util/flowmap.glsl"
|
||||||
|
|
||||||
#include "fog.glsl"
|
#include "fog.glsl"
|
||||||
#include "vertexcolors.glsl"
|
#include "vertexcolors.glsl"
|
||||||
@ -114,6 +120,8 @@ uniform sampler2D orthoDepthMap;
|
|||||||
varying vec3 orthoDepthMapCoord;
|
varying vec3 orthoDepthMapCoord;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uniform float osg_SimulationTime;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
#if @particleOcclusion
|
#if @particleOcclusion
|
||||||
@ -135,7 +143,12 @@ void main()
|
|||||||
vec2 screenCoords = gl_FragCoord.xy / screenRes;
|
vec2 screenCoords = gl_FragCoord.xy / screenRes;
|
||||||
|
|
||||||
#if @diffuseMap
|
#if @diffuseMap
|
||||||
|
|
||||||
|
#if @flowMap
|
||||||
|
gl_FragData[0] = applyFlowMap(diffuseMap, diffuseMapUV + offset, flowMap, flowMapUV, osg_SimulationTime);
|
||||||
|
#else
|
||||||
gl_FragData[0] = texture2D(diffuseMap, diffuseMapUV + offset);
|
gl_FragData[0] = texture2D(diffuseMap, diffuseMapUV + offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(DISTORTION) && DISTORTION
|
#if defined(DISTORTION) && DISTORTION
|
||||||
gl_FragData[0].a *= getDiffuseColor().a;
|
gl_FragData[0].a *= getDiffuseColor().a;
|
||||||
@ -163,7 +176,13 @@ vec2 screenCoords = gl_FragCoord.xy / screenRes;
|
|||||||
gl_FragData[0].a = alphaTest(gl_FragData[0].a, alphaRef);
|
gl_FragData[0].a = alphaTest(gl_FragData[0].a, alphaRef);
|
||||||
|
|
||||||
#if @normalMap
|
#if @normalMap
|
||||||
|
|
||||||
|
#if @flowMap
|
||||||
|
vec4 normalTex = applyFlowMap(normalMap, normalMapUV + offset, flowMap, flowMapUV, osg_SimulationTime);
|
||||||
|
#else
|
||||||
vec4 normalTex = texture2D(normalMap, normalMapUV + offset);
|
vec4 normalTex = texture2D(normalMap, normalMapUV + offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
vec3 normal = normalTex.xyz * 2.0 - 1.0;
|
vec3 normal = normalTex.xyz * 2.0 - 1.0;
|
||||||
#if @reconstructNormalZ
|
#if @reconstructNormalZ
|
||||||
normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
|
normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
|
||||||
@ -221,7 +240,13 @@ vec2 screenCoords = gl_FragCoord.xy / screenRes;
|
|||||||
specular = passSpecular + shadowSpecularLighting * shadowing;
|
specular = passSpecular + shadowSpecularLighting * shadowing;
|
||||||
#else
|
#else
|
||||||
#if @specularMap
|
#if @specularMap
|
||||||
|
|
||||||
|
#if @flowMap
|
||||||
|
vec4 specTex = applyFlowMap(specularMap, specularMapUV, flowMap, flowMapUV, osg_SimulationTime);
|
||||||
|
#else
|
||||||
vec4 specTex = texture2D(specularMap, specularMapUV);
|
vec4 specTex = texture2D(specularMap, specularMapUV);
|
||||||
|
#endif
|
||||||
|
|
||||||
float shininess = specTex.a * 255.0;
|
float shininess = specTex.a * 255.0;
|
||||||
vec3 specularColor = specTex.xyz;
|
vec3 specularColor = specTex.xyz;
|
||||||
#else
|
#else
|
||||||
|
@ -49,6 +49,10 @@ varying vec2 specularMapUV;
|
|||||||
varying vec2 glossMapUV;
|
varying vec2 glossMapUV;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if @flowMap
|
||||||
|
varying vec2 flowMapUV;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PER_PIXEL_LIGHTING (@normalMap || @specularMap || @forcePPL)
|
#define PER_PIXEL_LIGHTING (@normalMap || @specularMap || @forcePPL)
|
||||||
|
|
||||||
#if !PER_PIXEL_LIGHTING
|
#if !PER_PIXEL_LIGHTING
|
||||||
@ -147,6 +151,10 @@ void main(void)
|
|||||||
glossMapUV = (gl_TextureMatrix[@glossMapUV] * gl_MultiTexCoord@glossMapUV).xy;
|
glossMapUV = (gl_TextureMatrix[@glossMapUV] * gl_MultiTexCoord@glossMapUV).xy;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if @flowMap
|
||||||
|
flowMapUV = (gl_TextureMatrix[@flowMapUV] * gl_MultiTexCoord@flowMapUV).xy;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !PER_PIXEL_LIGHTING
|
#if !PER_PIXEL_LIGHTING
|
||||||
vec3 diffuseLight, ambientLight, specularLight;
|
vec3 diffuseLight, ambientLight, specularLight;
|
||||||
doLighting(viewPos.xyz, viewNormal, gl_FrontMaterial.shininess, diffuseLight, ambientLight, specularLight, shadowDiffuseLighting, shadowSpecularLighting);
|
doLighting(viewPos.xyz, viewNormal, gl_FrontMaterial.shininess, diffuseLight, ambientLight, specularLight, shadowDiffuseLighting, shadowSpecularLighting);
|
||||||
|
41
files/shaders/lib/util/flowmap.glsl
Normal file
41
files/shaders/lib/util/flowmap.glsl
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef LIB_UTIL_FLOWMAP
|
||||||
|
#define LIB_UTIL_FLOWMAP
|
||||||
|
|
||||||
|
uniform float flowMapStrength;
|
||||||
|
uniform float flowMapSpeed;
|
||||||
|
uniform float flowMapOffset;
|
||||||
|
uniform vec2 flowMapJump;
|
||||||
|
|
||||||
|
vec3 flowUVW(vec2 uv, vec2 flowVector, vec2 jump, float flowOffset, float time, float phaseOffset)
|
||||||
|
{
|
||||||
|
float alpha = fract(time + phaseOffset);
|
||||||
|
|
||||||
|
vec3 uvw = vec3(0.0);
|
||||||
|
uvw.xy = uv - flowVector * (alpha + flowOffset);
|
||||||
|
uvw.xy += phaseOffset;
|
||||||
|
uvw.xy += (time - alpha) * jump;
|
||||||
|
uvw.z = 1.0 - abs(1.0 - 2.0 * alpha);
|
||||||
|
|
||||||
|
return uvw;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 applyFlowMap(sampler2D tex, vec2 texUV, sampler2D flowMapTex, vec2 flowMapUV, float time)
|
||||||
|
{
|
||||||
|
// Based on https://catlikecoding.com/unity/tutorials/flow/texture-distortion/
|
||||||
|
// TODO: When using this on a normal map the blended normals are incorrect, does this need a unique function or is it 'good enough'?
|
||||||
|
vec2 flowVector = texture2D(flowMapTex, flowMapUV).xy * 2.0 - 1.0;
|
||||||
|
flowVector *= flowMapStrength;
|
||||||
|
|
||||||
|
float noise = texture2D(flowMapTex, flowMapUV).z;
|
||||||
|
time = time * flowMapSpeed + noise;
|
||||||
|
|
||||||
|
vec3 uvwA = flowUVW(texUV, flowVector, flowMapJump, flowMapOffset, time, 0.0);
|
||||||
|
vec3 uvwB = flowUVW(texUV, flowVector, flowMapJump, flowMapOffset, time, 0.5);
|
||||||
|
|
||||||
|
vec4 texA = texture2D(tex, uvwA.xy) * uvwA.z;
|
||||||
|
vec4 texB = texture2D(tex, uvwB.xy) * uvwB.z;
|
||||||
|
|
||||||
|
return texA + texB;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user