From a9f8e40f2c0784f0f2764dd23e04c6f6bca83c8d Mon Sep 17 00:00:00 2001 From: clementlandrin Date: Mon, 20 Jan 2025 11:17:49 +0100 Subject: [PATCH] Wrap VolumetricLighting.hx raymarching into raymarch function --- hrt/prefab/rfx/VolumetricLighting.hx | 919 ++++++++++++++------------- 1 file changed, 462 insertions(+), 457 deletions(-) diff --git a/hrt/prefab/rfx/VolumetricLighting.hx b/hrt/prefab/rfx/VolumetricLighting.hx index f8f387469..18ed0e2f5 100644 --- a/hrt/prefab/rfx/VolumetricLighting.hx +++ b/hrt/prefab/rfx/VolumetricLighting.hx @@ -1,458 +1,463 @@ -package hrt.prefab.rfx; - -class VolumetricLightingShader extends h3d.shader.pbr.DefaultForward { - - static var SRC = { - - @global var global : { - var time : Float; - } - - @param var invViewProj : Mat4; - - @param var noiseTurmoil : Float; - @param var noiseScale : Float; - @param var noiseLacunarity : Float; - @param var noisePersistence : Float; - @param var noiseSharpness : Float; - @param var noiseOctave : Int; - @param var noiseTex : Sampler2D; - - @param var depthMap : Sampler2D; - - @param var steps : Int; - @param var startDistance : Float; - @param var endDistance : Float; - @param var maxCamDist : Float = 0.0; - @param var distanceOpacity : Float; - - @param var ditheringNoise : Sampler2D; - @param var ditheringSize : Vec2; - @param var targetSize : Vec2; - @param var ditheringIntensity : Float; - - @param var color : Vec3; - @param var fogDensity : Float; - @param var fogUseNoise : Float; - @param var fogBottom : Float; - @param var fogTop : Float; - @param var fogHeightFalloff : Float; - @param var fogEnvPower : Float; - @param var fogEnvColorMult : Float; - - @param var secondFogColor : Vec3; - @param var secondFogDensity : Float; - @param var secondFogUseNoise : Float; - @param var secondFogBottom : Float; - @param var secondFogTop : Float; - @param var secondFogHeightFalloff : Float; - - var calculatedUV : Vec2; - var depthInvDimensions : Vec2; - - function noise( pos : Vec3 ) : Float { - var i = floor(pos); - var f = fract(pos); - f = f*f*(3.0-2.0*f); - var uv = (i.xy+vec2(37.0,239.0)*i.z) + f.xy; - var rg = noiseTex.getLod( (uv+0.5) / 256.0, 0 ).yx; - return mix( rg.x, rg.y, f.z ); - } - - function noiseAt( pos : Vec3 ) : Float { - var amount = 0.; - if ( noiseOctave > 0 ) { - var p = pos * 0.1 * noiseScale; - var t = global.time * noiseTurmoil; - amount += noise(p - t * vec3(0, 0, 1)); - var tot = 1.; - var k = noisePersistence; - p *= noiseLacunarity; - if ( noiseOctave >= 2 ) { - amount += noise(p + t * vec3(0, 0, -0.6)) * k; - k *= noisePersistence; - p *= noiseLacunarity; - tot += k; - } - if ( noiseOctave >= 3 ) { - amount += noise(p + t * vec3(-0.9, 0, 1.1)) * k; - k *= noisePersistence; - p *= noiseLacunarity; - tot += k; - } - if ( noiseOctave >= 4 ) { - amount += noise(p + t * vec3(0.8, 0.95,-1.2)) * k; - k *= noisePersistence; - p *= noiseLacunarity; - tot += k; - } - - if ( noiseOctave >= 5 ) { - amount += noise(p + t * vec3(0,-0.84,-1.3)) * k; - tot += k; - p *= noiseLacunarity; - k *= noisePersistence; - tot += k; - } - amount = pow(amount / tot, noiseSharpness); - } else { - amount = 1.0; - } - return amount; - } - - function indirectLighting() : Vec3 { - return envColor * irrPower * fogEnvPower; - } - - function getFogColor() : Vec3 { - return mix(color, secondFogColor, useSecondColor); - } - - function directLighting(lightColor : Vec3, lightDirection : Vec3) : Vec3 { - return lightColor; - } - - function pointLightIntensity( delta : Vec3, size : Float, invRange4 : Float ) : Float { - var dist = delta.dot(delta); - var falloff = saturate(1 - dist*dist * invRange4); - if( size > 0 ) { - dist = (dist.sqrt() - size).max(0.); - dist *= dist; - } - falloff *= falloff; - return falloff * falloff * exp(-fog * dist); - } - - var useSecondColor : Float; - function fogAt(pos : Vec3) : Float { - var n = noiseAt(pos); - var hNorm = smoothstep(0.0, 1.0, (pos.z - fogBottom) / (fogTop - fogBottom)); - var firstFog = exp(-hNorm * fogHeightFalloff) * (1.0 - hNorm) * fogDensity; - - var secondHNorm = smoothstep(0.0, 1.0, (pos.z - secondFogBottom) / (secondFogTop - secondFogBottom)); - var secondFog = exp(-secondHNorm * secondFogHeightFalloff) * (1.0 - secondHNorm) * secondFogDensity; - firstFog *= mix(1.0, n, fogUseNoise); - secondFog *= mix(1.0, n, secondFogUseNoise); - - useSecondColor = saturate(secondFog / max(firstFog, secondFog)); - return max(firstFog, secondFog); - } - - function getWPos() : Vec3 { - var pixels = fragCoord.xy; - var depth = depthMap.get( pixels * depthInvDimensions ).r; - var uv2 = uvToScreen(calculatedUV); - var temp = vec4(uv2, depth, 1) * invViewProj; - return temp.xyz / temp.w; - } - - function getDistBlend(dist: Float) : Float { - var dfactor = smoothstep(0, 1, dist / endDistance); - return dfactor * dfactor; - } - - var camDir : Vec3; - var envColor : Vec3; - var fog : Float; - function fragment() { - metalness = 0.0; - emissive = 0.0; - albedoGamma = vec3(0.0); - useSecondColor = 0.0; - - depthInvDimensions = 1.0 / depthMap.size(); - var endPos = getWPos(); - - camDir = normalize(endPos - camera.position); - var startPos = camera.position + camDir * startDistance; - var cameraDistance = length(endPos - startPos); - if ( dot(camDir, endPos - startPos) < 0.0 ) - discard; - if ( maxCamDist > 0.0 ) - cameraDistance = min(cameraDistance, maxCamDist); - endPos = startPos + camDir * cameraDistance; - - envColor = irrDiffuse.getLod(-camDir, 0.0).rgb; - view = -camDir; - - var stepSize = length(endPos - startPos) / float(steps); - var dithering = ditheringNoise.getLod(calculatedUV * targetSize / ditheringSize, 0.0).r * stepSize * ditheringIntensity; - startPos += dithering * camDir; - var opacity = 0.0; - var totalScattered = vec3(0.0); - var opticalDepth = 0.0; - pixelColor = vec4(1.0); - var colorAcc = vec4(0.0); - var curDist = 0.0; - for ( i in 0...steps ) { - if ( colorAcc.a > 0.99 ) - break; - transformedPosition = startPos + camDir * curDist; - fog = fogAt(transformedPosition); - var fColor = getFogColor(); - var stepColor = evaluateLighting() * fColor * mix(vec3(1.0), saturate(envColor), fogEnvColorMult); - - var stepColor = vec4(stepColor * fog, fog); - - colorAcc += stepColor * (1.0 - colorAcc.a) * getDistBlend(curDist) * stepSize; - - curDist += stepSize; - } - pixelColor.rgb = colorAcc.rgb / (0.001 + colorAcc.a); - pixelColor.a = saturate(distanceOpacity * colorAcc.a); - } - }; -} - -@:access(h3d.scene.Renderer) -class VolumetricLighting extends RendererFX { - - var pass = new h3d.pass.ScreenFx(new h3d.shader.ScreenShader()); - var halfingDepthPass = new h3d.pass.ScreenFx(new h3d.shader.CheckerboardDepth() ); - var upsamplingPass = new h3d.pass.ScreenFx(new h3d.shader.DepthAwareUpsampling()); - - var blurPass = new h3d.pass.Blur(); - var vshader = new VolumetricLightingShader(); - - @:s public var AFTER_FX : Bool = false; - @:s public var blend : h3d.mat.PbrMaterial.PbrBlend = Alpha; - @:s public var color : Int = 0xFFFFFF; - @:s public var steps : Int = 10; - @:s public var blur : Float = 0.0; - @:s public var blurDepthThreshold : Float = 10.0; - @:s public var startDistance : Float = 0.0; - @:s public var endDistance : Float = 200.0; - @:s public var distanceOpacity : Float = 1.0; - @:s public var ditheringIntensity : Float = 1.0; - - @:s public var noiseScale : Float = 1.0; - @:s public var noiseLacunarity : Float = 2.0; - @:s public var noiseSharpness : Float = 1.0; - @:s public var noisePersistence : Float = 0.5; - @:s public var noiseTurmoil : Float = 1.0; - @:s public var noiseOctave : Int = 1; - - @:s public var fogDensity : Float = 1.0; - @:s public var fogUseNoise : Float = 1.0; - @:s public var fogHeightFalloff : Float = 1.0; - @:s public var fogEnvPower : Float = 1.0; - @:s public var fogBottom : Float = 0.0; - @:s public var fogTop : Float = 200.0; - @:s public var fogEnvColorMult : Float = 0.0; - - @:s public var secondFogColor : Int = 0xFFFFFF; - @:s public var secondFogUseNoise : Float = 1.0; - @:s public var secondFogDensity : Float = 0.0; - @:s public var secondFogHeightFalloff : Float = 5.0; - @:s public var secondFogBottom : Float = 0.0; - @:s public var secondFogTop : Float = 50.0; - - var noiseTex : h3d.mat.Texture; - - function execute(r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step) { - if( step == BeforeTonemapping ) { - var r = cast(r, h3d.scene.pbr.Renderer); - r.mark("VolumetricLighting"); - - if ( noiseTex == null ) - noiseTex = makeNoiseTex(); - - var depth = r.textures.albedo.depthBuffer; - - var prevFilter = depth.filter; - depth.filter = Nearest; - - var halfDepth = r.allocTarget("halfDepth", false, 0.5, R32F); - halfDepth.filter = Nearest; - r.ctx.engine.pushTarget(halfDepth); - halfingDepthPass.shader.source = depth; - halfingDepthPass.shader.texRatio = 2.0; - halfingDepthPass.render(); - r.ctx.engine.popTarget(); - - var tex = r.allocTarget("volumetricLighting", false, 0.5, RGBA16F); - tex.clear(0, 0.0); - r.ctx.engine.pushTarget(tex); - - vshader.USE_INDIRECT = false; - if ( pass.getShader(h3d.shader.pbr.DefaultForward) == null ) - pass.addShader(vshader); - var ls = cast(r.getLightSystem(), h3d.scene.pbr.LightSystem); - ls.lightBuffer.setBuffers(vshader); - vshader.depthMap = halfDepth; - vshader.startDistance = startDistance; - vshader.endDistance = endDistance; - vshader.distanceOpacity = distanceOpacity; - vshader.steps = steps; - vshader.invViewProj = r.ctx.camera.getInverseViewProj(); - if ( vshader.ditheringNoise == null ) { - vshader.ditheringNoise = hxd.res.Embed.getResource("hrt/prefab/rfx/blueNoise.png").toImage().toTexture(); - vshader.ditheringNoise.wrap = Repeat; - } - vshader.targetSize.set(tex.width, tex.height); - vshader.ditheringSize.set(vshader.ditheringNoise.width, vshader.ditheringNoise.height); - vshader.ditheringIntensity = ditheringIntensity; - vshader.noiseTex = noiseTex; - vshader.noiseScale = noiseScale; - vshader.noiseOctave = noiseOctave; - vshader.noiseTurmoil = noiseTurmoil; - vshader.noiseSharpness = noiseSharpness; - vshader.noisePersistence = noisePersistence; - vshader.noiseLacunarity = noiseLacunarity; - vshader.fogEnvPower = fogEnvPower; - - vshader.color.load(h3d.Vector.fromColor(color)); - vshader.fogDensity = fogDensity * 0.002; - vshader.fogUseNoise = fogUseNoise; - vshader.fogBottom = fogBottom; - vshader.fogTop = fogTop; - vshader.fogEnvColorMult = fogEnvColorMult; - vshader.fogHeightFalloff = fogHeightFalloff; - - vshader.secondFogColor.load(h3d.Vector.fromColor(secondFogColor)); - vshader.secondFogDensity = secondFogDensity * 0.002; - vshader.secondFogUseNoise = secondFogUseNoise; - vshader.secondFogBottom = secondFogBottom; - vshader.secondFogTop = secondFogTop; - vshader.secondFogHeightFalloff = secondFogHeightFalloff; - pass.pass.setBlendMode(Alpha); - pass.render(); - - r.ctx.engine.popTarget(); - - var inverseProj = r.ctx.camera.getInverseProj(); - - blurPass.radius = blur; - blurPass.shader.isDepthDependant = true; - blurPass.shader.depthTexture = halfDepth; - blurPass.shader.inverseProj = inverseProj; - blurPass.shader.depthThreshold = blurDepthThreshold; - blurPass.apply(r.ctx, tex); - - var b : h3d.mat.BlendMode = switch ( blend ) { - case None: None; - case Alpha: Alpha; - case Add: Add; - case AlphaAdd: AlphaAdd; - case Multiply: Multiply; - case AlphaMultiply: AlphaMultiply; - } - - r.ctx.engine.pushTarget(r.textures.hdr, 0, 0, NotBound); - upsamplingPass.pass.setBlendMode(b); - upsamplingPass.shader.source = tex; - upsamplingPass.shader.sourceDepth = halfDepth; - upsamplingPass.shader.destDepth = depth; - upsamplingPass.shader.inverseProj = inverseProj; - upsamplingPass.render(); - r.ctx.engine.popTarget(); - - depth.filter = prevFilter; - } - } - - override function begin(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { - if ( !AFTER_FX ) - execute(r, step); - } - - override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { - if ( AFTER_FX ) - execute(r, step); - } - - function makeNoiseTex() : h3d.mat.Texture { - var rands : Array = []; - var rand = new hxd.Rand(0); - for(x in 0...256) - for(y in 0...256) - rands.push(rand.random(256)); - var pix = hxd.Pixels.alloc(256, 256, RGBA); - for(x in 0...256) { - for(y in 0...256) { - var r = rands[x + y * 256]; - var g = rands[((x - 37) & 255) + ((y - 239) & 255) * 256]; - var off = (x + y*256) * 4; - pix.bytes.set(off, r); - pix.bytes.set(off+1, g); - pix.bytes.set(off+3, 255); - } - } - var tex = new h3d.mat.Texture(pix.width, pix.height, [], RGBA); - tex.uploadPixels(pix); - tex.wrap = Repeat; - return tex; - } - - #if editor - - override function edit( ctx : hide.prefab.EditContext ) { - super.edit(ctx); - ctx.properties.add(new hide.Element( - '
-
-
Blend
-
- -
-
After fx
-
Begin
-
Start distance
-
End distance
-
Distance opacity
-
Env power
-
Env color mult
-
Color
-
Density
-
Use noise
-
Bottom [m]
-
Top [m]
-
Height falloff
-
-
-
-
-
Color
-
Density
-
Use noise
-
Bottom [m]
-
Top [m]
-
Height falloff
-
-
-
-
-
Octaves
-
Scale
-
Turmoil
-
Persistence
-
Lacunarity
-
Sharpness
-
-
-
-
-
Steps
-
Blur
-
Blur depth threshold
-
Dithering intensity
-
-
- '), this, function(pname) { - ctx.onChange(this, pname); - }); - } - - #end - - static var _ = Prefab.register("rfx.volumetricLighting", VolumetricLighting); - +package hrt.prefab.rfx; + +class VolumetricLightingShader extends h3d.shader.pbr.DefaultForward { + + static var SRC = { + + @global var global : { + var time : Float; + } + + @param var invViewProj : Mat4; + + @param var noiseTurmoil : Float; + @param var noiseScale : Float; + @param var noiseLacunarity : Float; + @param var noisePersistence : Float; + @param var noiseSharpness : Float; + @param var noiseOctave : Int; + @param var noiseTex : Sampler2D; + + @param var halfDepthMap : Sampler2D; + + @param var steps : Int; + @param var startDistance : Float; + @param var endDistance : Float; + @param var maxCamDist : Float = 0.0; + @param var distanceOpacity : Float; + + @param var ditheringNoise : Sampler2D; + @param var ditheringSize : Vec2; + @param var targetSize : Vec2; + @param var ditheringIntensity : Float; + + @param var color : Vec3; + @param var fogDensity : Float; + @param var fogUseNoise : Float; + @param var fogBottom : Float; + @param var fogTop : Float; + @param var fogHeightFalloff : Float; + @param var fogEnvPower : Float; + @param var fogEnvColorMult : Float; + + @param var secondFogColor : Vec3; + @param var secondFogDensity : Float; + @param var secondFogUseNoise : Float; + @param var secondFogBottom : Float; + @param var secondFogTop : Float; + @param var secondFogHeightFalloff : Float; + + var calculatedUV : Vec2; + + function noise( pos : Vec3 ) : Float { + var i = floor(pos); + var f = fract(pos); + f = f*f*(3.0-2.0*f); + var uv = (i.xy+vec2(37.0,239.0)*i.z) + f.xy; + var rg = noiseTex.getLod( (uv+0.5) / 256.0, 0 ).yx; + return mix( rg.x, rg.y, f.z ); + } + + function noiseAt( pos : Vec3 ) : Float { + var amount = 0.; + if ( noiseOctave > 0 ) { + var p = pos * 0.1 * noiseScale; + var t = global.time * noiseTurmoil; + amount += noise(p - t * vec3(0, 0, 1)); + var tot = 1.; + var k = noisePersistence; + p *= noiseLacunarity; + if ( noiseOctave >= 2 ) { + amount += noise(p + t * vec3(0, 0, -0.6)) * k; + k *= noisePersistence; + p *= noiseLacunarity; + tot += k; + } + if ( noiseOctave >= 3 ) { + amount += noise(p + t * vec3(-0.9, 0, 1.1)) * k; + k *= noisePersistence; + p *= noiseLacunarity; + tot += k; + } + if ( noiseOctave >= 4 ) { + amount += noise(p + t * vec3(0.8, 0.95,-1.2)) * k; + k *= noisePersistence; + p *= noiseLacunarity; + tot += k; + } + + if ( noiseOctave >= 5 ) { + amount += noise(p + t * vec3(0,-0.84,-1.3)) * k; + tot += k; + p *= noiseLacunarity; + k *= noisePersistence; + tot += k; + } + amount = pow(amount / tot, noiseSharpness); + } else { + amount = 1.0; + } + return amount; + } + + function indirectLighting() : Vec3 { + return envColor * irrPower * fogEnvPower; + } + + function getFogColor() : Vec3 { + return mix(color, secondFogColor, useSecondColor); + } + + function directLighting(lightColor : Vec3, lightDirection : Vec3) : Vec3 { + return lightColor; + } + + function pointLightIntensity( delta : Vec3, size : Float, invRange4 : Float ) : Float { + var dist = delta.dot(delta); + var falloff = saturate(1 - dist*dist * invRange4); + if( size > 0 ) { + dist = (dist.sqrt() - size).max(0.); + dist *= dist; + } + falloff *= falloff; + return falloff * falloff * exp(-fog * dist); + } + + var useSecondColor : Float; + function fogAt(pos : Vec3) : Float { + var n = noiseAt(pos); + var hNorm = smoothstep(0.0, 1.0, (pos.z - fogBottom) / (fogTop - fogBottom)); + var firstFog = exp(-hNorm * fogHeightFalloff) * (1.0 - hNorm) * fogDensity; + + var secondHNorm = smoothstep(0.0, 1.0, (pos.z - secondFogBottom) / (secondFogTop - secondFogBottom)); + var secondFog = exp(-secondHNorm * secondFogHeightFalloff) * (1.0 - secondHNorm) * secondFogDensity; + firstFog *= mix(1.0, n, fogUseNoise); + secondFog *= mix(1.0, n, secondFogUseNoise); + + useSecondColor = saturate(secondFog / max(firstFog, secondFog)); + return max(firstFog, secondFog); + } + + function getWPos() : Vec3 { var depth = halfDepthMap.get( fragCoord.xy / halfDepthMap.size() ).r; + var uv2 = uvToScreen(calculatedUV); + var temp = vec4(uv2, depth, 1) * invViewProj; + return temp.xyz / temp.w; + } + + function getDistBlend(dist: Float) : Float { + var dfactor = smoothstep(0, 1, dist / endDistance); + return dfactor * dfactor; + } + + var camDir : Vec3; + var envColor : Vec3; + var fog : Float; + function rayMarch() : Vec4 { + metalness = 0.0; + emissive = 0.0; + albedoGamma = vec3(0.0); + useSecondColor = 0.0; + + var endPos = getWPos(); + camDir = normalize(endPos - camera.position); + var startPos = camera.position + camDir * startDistance; + var cameraDistance = length(endPos - startPos); + if ( dot(camDir, endPos - startPos) < 0.0 ) + discard; + if ( maxCamDist > 0.0 ) + cameraDistance = min(cameraDistance, maxCamDist); + endPos = startPos + camDir * cameraDistance; + + envColor = irrDiffuse.getLod(-camDir, 0.0).rgb; + view = -camDir; + + var stepSize = length(endPos - startPos) / float(steps); + var dithering = ditheringNoise.getLod(calculatedUV * targetSize / ditheringSize, 0.0).r * stepSize * ditheringIntensity; + startPos += dithering * camDir; + var opacity = 0.0; + var totalScattered = vec3(0.0); + var opticalDepth = 0.0; + var prevPixelColor = pixelColor; + pixelColor = vec4(1.0); + var colorAcc = vec4(0.0); + var curDist = 0.0; + for ( i in 0...steps ) { + if ( colorAcc.a > 0.99 ) + break; + transformedPosition = startPos + camDir * curDist; + fog = fogAt(transformedPosition); + var fColor = getFogColor(); + var stepColor = evaluateLighting() * fColor * mix(vec3(1.0), saturate(envColor), fogEnvColorMult); + + var stepColor = vec4(stepColor * fog, fog); + + colorAcc += stepColor * (1.0 - colorAcc.a) * getDistBlend(curDist) * stepSize; + + curDist += stepSize; + } + var outColor = colorAcc.rgb / (0.001 + colorAcc.a); + var opacity = saturate(distanceOpacity * colorAcc.a); + + return vec4(outColor, opacity); + } + + function fragment() { + pixelColor = rayMarch(); + } + } +} + +@:access(h3d.scene.Renderer) +class VolumetricLighting extends RendererFX { + + var pass = new h3d.pass.ScreenFx(new h3d.shader.ScreenShader()); + var halfingDepthPass = new h3d.pass.ScreenFx(new h3d.shader.CheckerboardDepth() ); + var upsamplingPass = new h3d.pass.ScreenFx(new h3d.shader.DepthAwareUpsampling()); + + var blurPass = new h3d.pass.Blur(); + var vshader = new VolumetricLightingShader(); + + @:s public var AFTER_FX : Bool = false; + @:s public var blend : h3d.mat.PbrMaterial.PbrBlend = Alpha; + @:s public var color : Int = 0xFFFFFF; + @:s public var steps : Int = 10; + @:s public var blur : Float = 0.0; + @:s public var blurDepthThreshold : Float = 10.0; + @:s public var startDistance : Float = 0.0; + @:s public var endDistance : Float = 200.0; + @:s public var distanceOpacity : Float = 1.0; + @:s public var ditheringIntensity : Float = 1.0; + + @:s public var noiseScale : Float = 1.0; + @:s public var noiseLacunarity : Float = 2.0; + @:s public var noiseSharpness : Float = 1.0; + @:s public var noisePersistence : Float = 0.5; + @:s public var noiseTurmoil : Float = 1.0; + @:s public var noiseOctave : Int = 1; + + @:s public var fogDensity : Float = 1.0; + @:s public var fogUseNoise : Float = 1.0; + @:s public var fogHeightFalloff : Float = 1.0; + @:s public var fogEnvPower : Float = 1.0; + @:s public var fogBottom : Float = 0.0; + @:s public var fogTop : Float = 200.0; + @:s public var fogEnvColorMult : Float = 0.0; + + @:s public var secondFogColor : Int = 0xFFFFFF; + @:s public var secondFogUseNoise : Float = 1.0; + @:s public var secondFogDensity : Float = 0.0; + @:s public var secondFogHeightFalloff : Float = 5.0; + @:s public var secondFogBottom : Float = 0.0; + @:s public var secondFogTop : Float = 50.0; + + var noiseTex : h3d.mat.Texture; + + function execute(r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step) { + if( step == BeforeTonemapping ) { + if ( distanceOpacity <= 0.0 ) + return; + + var r = cast(r, h3d.scene.pbr.Renderer); + r.mark("VolumetricLighting"); + + if ( noiseTex == null ) + noiseTex = makeNoiseTex(); + + var depth = r.textures.albedo.depthBuffer; + + var prevFilter = depth.filter; + depth.filter = Nearest; + + var halfDepth = r.allocTarget("halfDepth", false, 0.5, R32F); + halfDepth.filter = Nearest; + r.ctx.engine.pushTarget(halfDepth); + halfingDepthPass.shader.source = depth; + halfingDepthPass.shader.texRatio = 2.0; + halfingDepthPass.render(); + r.ctx.engine.popTarget(); + + var tex = r.allocTarget("volumetricLighting", false, 0.5, RGBA16F); + tex.clear(0, 0.0); + r.ctx.engine.pushTarget(tex); + + vshader.USE_INDIRECT = false; + if ( pass.getShader(h3d.shader.pbr.DefaultForward) == null ) + pass.addShader(vshader); + var ls = cast(r.getLightSystem(), h3d.scene.pbr.LightSystem); + ls.lightBuffer.setBuffers(vshader); + vshader.halfDepthMap = halfDepth; + vshader.startDistance = startDistance; + vshader.endDistance = endDistance; + vshader.distanceOpacity = distanceOpacity; + vshader.steps = steps; + vshader.invViewProj = r.ctx.camera.getInverseViewProj(); + if ( vshader.ditheringNoise == null ) { + vshader.ditheringNoise = hxd.res.Embed.getResource("hrt/prefab/rfx/blueNoise.png").toImage().toTexture(); + vshader.ditheringNoise.wrap = Repeat; + } + vshader.targetSize.set(tex.width, tex.height); + vshader.ditheringSize.set(vshader.ditheringNoise.width, vshader.ditheringNoise.height); + vshader.ditheringIntensity = ditheringIntensity; + vshader.noiseTex = noiseTex; + vshader.noiseScale = noiseScale; + vshader.noiseOctave = noiseOctave; + vshader.noiseTurmoil = noiseTurmoil; + vshader.noiseSharpness = noiseSharpness; + vshader.noisePersistence = noisePersistence; + vshader.noiseLacunarity = noiseLacunarity; + vshader.fogEnvPower = fogEnvPower; + + vshader.color.load(h3d.Vector.fromColor(color)); + vshader.fogDensity = fogDensity * 0.002; + vshader.fogUseNoise = fogUseNoise; + vshader.fogBottom = fogBottom; + vshader.fogTop = fogTop; + vshader.fogEnvColorMult = fogEnvColorMult; + vshader.fogHeightFalloff = fogHeightFalloff; + + vshader.secondFogColor.load(h3d.Vector.fromColor(secondFogColor)); + vshader.secondFogDensity = secondFogDensity * 0.002; + vshader.secondFogUseNoise = secondFogUseNoise; + vshader.secondFogBottom = secondFogBottom; + vshader.secondFogTop = secondFogTop; + vshader.secondFogHeightFalloff = secondFogHeightFalloff; + pass.pass.setBlendMode(Alpha); + pass.render(); + + r.ctx.engine.popTarget(); + + var inverseProj = r.ctx.camera.getInverseProj(); + + blurPass.radius = blur; + blurPass.shader.isDepthDependant = true; + blurPass.shader.depthTexture = halfDepth; + blurPass.shader.inverseProj = inverseProj; + blurPass.shader.depthThreshold = blurDepthThreshold; + blurPass.apply(r.ctx, tex); + + var b : h3d.mat.BlendMode = switch ( blend ) { + case None: None; + case Alpha: Alpha; + case Add: Add; + case AlphaAdd: AlphaAdd; + case Multiply: Multiply; + case AlphaMultiply: AlphaMultiply; + } + + r.ctx.engine.pushTarget(r.textures.hdr, 0, 0, NotBound); + upsamplingPass.pass.setBlendMode(b); + upsamplingPass.shader.source = tex; + upsamplingPass.shader.sourceDepth = halfDepth; + upsamplingPass.shader.destDepth = depth; + upsamplingPass.shader.inverseProj = inverseProj; + upsamplingPass.render(); + r.ctx.engine.popTarget(); + + depth.filter = prevFilter; + } + } + + override function begin(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { + if ( !AFTER_FX ) + execute(r, step); + } + + override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) { + if ( AFTER_FX ) + execute(r, step); + } + + function makeNoiseTex() : h3d.mat.Texture { + var rands : Array = []; + var rand = new hxd.Rand(0); + for(x in 0...256) + for(y in 0...256) + rands.push(rand.random(256)); + var pix = hxd.Pixels.alloc(256, 256, RGBA); + for(x in 0...256) { + for(y in 0...256) { + var r = rands[x + y * 256]; + var g = rands[((x - 37) & 255) + ((y - 239) & 255) * 256]; + var off = (x + y*256) * 4; + pix.bytes.set(off, r); + pix.bytes.set(off+1, g); + pix.bytes.set(off+3, 255); + } + } + var tex = new h3d.mat.Texture(pix.width, pix.height, [], RGBA); + tex.uploadPixels(pix); + tex.wrap = Repeat; + return tex; + } + + #if editor + + override function edit( ctx : hide.prefab.EditContext ) { + super.edit(ctx); + ctx.properties.add(new hide.Element( + '
+
+
Blend
+
+ +
+
After fx
+
Begin
+
Start distance
+
End distance
+
Distance opacity
+
Env power
+
Env color mult
+
Color
+
Density
+
Use noise
+
Bottom [m]
+
Top [m]
+
Height falloff
+
+
+
+
+
Color
+
Density
+
Use noise
+
Bottom [m]
+
Top [m]
+
Height falloff
+
+
+
+
+
Octaves
+
Scale
+
Turmoil
+
Persistence
+
Lacunarity
+
Sharpness
+
+
+
+
+
Steps
+
Blur
+
Blur depth threshold
+
Dithering intensity
+
+
+ '), this, function(pname) { + ctx.onChange(this, pname); + }); + } + + #end + + static var _ = Prefab.register("rfx.volumetricLighting", VolumetricLighting); + } \ No newline at end of file