diff --git a/src/InstanceManager.hx b/src/InstanceManager.hx index 2b4b01eb..71c0d77d 100644 --- a/src/InstanceManager.hx +++ b/src/InstanceManager.hx @@ -74,9 +74,11 @@ class InstanceManager { dtsShader.currentOpacity = instance.gameObject.currentOpacity; } var transform = instance.emptyObj.getAbsPos(); - minfo.meshbatch.shadersChanged = true; + minfo.meshbatch.material.mainPass.depthWrite = minfo.mesh.material.mainPass.depthWrite; + minfo.meshbatch.material.mainPass.depthTest = minfo.mesh.material.mainPass.depthTest; + // minfo.meshbatch.shadersChanged = true; minfo.meshbatch.material.mainPass.setPassName(minfo.mesh.material.mainPass.name); - minfo.meshbatch.material.mainPass.enableLights = minfo.mesh.material.mainPass.enableLights; + // minfo.meshbatch.material.mainPass.enableLights = minfo.mesh.material.mainPass.enableLights; minfo.meshbatch.worldPosition = transform; minfo.meshbatch.emitInstance(); } @@ -147,6 +149,10 @@ class InstanceManager { for (shader in mat.mainPass.getShaders()) { minfo.meshbatch.material.mainPass.addShader(shader); } + var glowPass = mat.getPass("glow"); + if (glowPass != null) { + minfo.meshbatch.material.addPass(glowPass.clone()); + } // var dtsshader = mat.mainPass.getShader(DtsTexture); // if (dtsshader != null) { // minfo.meshbatch.material.mainPass.removeShader(minfo.meshbatch.material.textureShader); diff --git a/src/Main.hx b/src/Main.hx index d2bc95e0..b47646fa 100644 --- a/src/Main.hx +++ b/src/Main.hx @@ -22,6 +22,7 @@ import h3d.Vector; import src.ProfilerUI; import src.Gamepad; import src.Http; +import src.Renderer; class Main extends hxd.App { var marbleGame:MarbleGame; @@ -35,6 +36,8 @@ class Main extends hxd.App { override function init() { super.init(); + s3d.renderer = new Renderer(); + #if (hl && !android) hl.UI.closeConsole(); #end diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 1559e569..0c4e9c00 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -294,7 +294,7 @@ class MarbleWorld extends Scheduler { this.particleManager = new ParticleManager(cast this); var worker = new ResourceLoaderWorker(() -> { - var renderer = cast(this.scene.renderer, h3d.scene.fwd.Renderer); + var renderer = cast(this.scene.renderer, src.Renderer); for (element in mission.root.elements) { if (element._type != MissionElementType.Sun) diff --git a/src/Renderer.hx b/src/Renderer.hx new file mode 100644 index 00000000..863bca31 --- /dev/null +++ b/src/Renderer.hx @@ -0,0 +1,152 @@ +package src; + +import h3d.Vector; +import shaders.Blur; +import h3d.pass.ScreenFx; +import h3d.mat.DepthBuffer; + +class Renderer extends h3d.scene.Renderer { + var def(get, never):h3d.pass.Base; + + public var depth:h3d.pass.Base = new h3d.scene.fwd.Renderer.DepthPass(); + public var normal:h3d.pass.Base = new h3d.scene.fwd.Renderer.NormalPass(); + public var shadow = new h3d.pass.DefaultShadowMap(1024); + + var glowBuffer:h3d.mat.Texture; + var backBuffers:Array; + var curentBackBuffer = 0; + var blurShader:ScreenFx; + var growBufferTemps:Array; + var copyPass:h3d.pass.Copy; + var backBuffer:h3d.mat.Texture; + + public function new() { + super(); + defaultPass = new h3d.pass.Default("default"); + allPasses = [defaultPass, depth, normal, shadow]; + blurShader = new ScreenFx(new Blur()); + copyPass = new h3d.pass.Copy(); + } + + inline function get_def() + return defaultPass; + + public inline function getBackBuffer():h3d.mat.Texture { + return backBuffers[1]; + } + + // can be overriden for benchmark purposes + function renderPass(p:h3d.pass.Base, passes, ?sort) { + p.draw(passes, sort); + } + + override function getPassByName(name:String):h3d.pass.Base { + if (name == "alpha" || name == "additive" || name == "glowPre" || name == "glow") + return defaultPass; + return super.getPassByName(name); + } + + override function render() { + if (backBuffer == null) { + backBuffer = ctx.textures.allocTarget("backBuffer", ctx.engine.width, ctx.engine.height); + } + ctx.engine.pushTarget(backBuffer); + ctx.engine.clear(0, 1); + + if (has("shadow")) + renderPass(shadow, get("shadow")); + + if (has("depth")) + renderPass(depth, get("depth")); + + if (has("normal")) + renderPass(normal, get("normal")); + + if (backBuffers == null) { + var commonDepth = new DepthBuffer(ctx.engine.width, ctx.engine.height); + backBuffers = [ + ctx.textures.allocTarget("backbuffer1", 320, 320, false), + ctx.textures.allocTarget("backbuffer2", 320, 320, false), + ]; + backBuffers[0].depthBuffer = commonDepth; + // backBuffers[1].depthBuffer = commonDepth; + // new h3d.mat.Texture(ctx.engine.width, ctx.engine.height, [Target]); + // refractTexture.depthBuffer = new DepthBuffer(ctx.engine.width, ctx.engine.height); + } + if (growBufferTemps == null) { + glowBuffer = ctx.textures.allocTarget("glowBuffer", ctx.engine.width, ctx.engine.height); + growBufferTemps = [ + ctx.textures.allocTarget("gb1", 320, 320, false), + ctx.textures.allocTarget("gb2", 320, 320, false), + ]; + } + // ctx.engine.pushTarget(backBuffers[0]); + // ctx.engine.clear(0, 1); + + renderPass(defaultPass, get("sky")); + renderPass(defaultPass, get("skyshape"), backToFront); + renderPass(defaultPass, get("default")); + renderPass(defaultPass, get("glowPre")); + + ctx.engine.pushTarget(glowBuffer); + ctx.engine.clear(0); + renderPass(defaultPass, get("glow")); + bloomPass(ctx); + ctx.engine.popTarget(); + copyPass.shader.texture = growBufferTemps[0]; + copyPass.pass.blend(One, One); + copyPass.pass.depth(false, Always); + copyPass.render(); + + renderPass(defaultPass, get("alpha"), backToFront); + renderPass(defaultPass, get("additive")); + + ctx.engine.popTarget(); + + copyPass.pass.blend(One, Zero); + copyPass.shader.texture = backBuffer; + copyPass.render(); + + // h3d.pass.Copy.run(backBuffers[0], backBuffers[1]); + // renderPass(defaultPass, get("refract")); + // ctx.engine.popTarget(); + // h3d.pass.Copy.run(backBuffers[0], null); + + // curentBackBuffer = 1 - curentBackBuffer; + } + + function bloomPass(ctx:h3d.scene.RenderContext) { + h3d.pass.Copy.run(glowBuffer, growBufferTemps[0]); + + var offsets = [-7.5, -6.25, -5, -3.75, -2.5, -1.25, 0, 1.25, 2.5, 3.75, 5, 6.25, 7.5]; + var divisors = [0.1, 0.3, 0.4, 0.5, 0.6, 0.7, 1.0, 0.7, 0.5, 0.5, 0.4, 0.3, 0.1]; + + var divisor = 0.0; + + var kernel = []; + for (i in 0...13) { + kernel.push(new Vector(offsets[i] / 320, 0, divisors[i])); + divisor += divisors[i]; + } + + blurShader.shader.kernel = kernel; + blurShader.shader.divisor = divisor; + blurShader.shader.texture = growBufferTemps[0]; + ctx.engine.pushTarget(growBufferTemps[1]); + ctx.engine.clear(0, 1); + blurShader.render(); + ctx.engine.popTarget(); + + for (i in 0...13) { + kernel[i].set(0, offsets[i] / 320, divisors[i]); + } + + blurShader.shader.kernel = kernel; + blurShader.shader.divisor = divisor; + blurShader.shader.texture = growBufferTemps[1]; + ctx.engine.pushTarget(growBufferTemps[0]); + ctx.engine.clear(0, 1); + blurShader.render(); + ctx.engine.popTarget(); + } +} diff --git a/src/Sky.hx b/src/Sky.hx index 63e7ab03..a5773991 100644 --- a/src/Sky.hx +++ b/src/Sky.hx @@ -58,6 +58,7 @@ class Sky extends Object { skyMesh.material.mainPass.addShader(shad); skyMesh.material.mainPass.depthWrite = false; skyMesh.material.mainPass.depth(false, h3d.mat.Data.Compare.LessEqual); + skyMesh.material.mainPass.setPassName("sky"); cubemap = texture; onFinish(); }); diff --git a/src/shaders/Blur.hx b/src/shaders/Blur.hx new file mode 100644 index 00000000..0162326e --- /dev/null +++ b/src/shaders/Blur.hx @@ -0,0 +1,20 @@ +package shaders; + +import h3d.shader.ScreenShader; + +class Blur extends ScreenShader { + static var SRC = { + @param var texture:Sampler2D; + @param var kernel:Array; + @param var divisor:Float; + function fragment() { + var accumColor = vec4(0); + for (i in 0...13) { + accumColor += texture.get(input.uv + kernel[i].xy) * kernel[i].z; + } + pixelColor = accumColor / divisor; + pixelColor.a = pixelColor.x + pixelColor.y + pixelColor.z / 3.0; + pixelColor.xyz *= 2.0; + } + }; +} diff --git a/src/shaders/TrivialMaterial.hx b/src/shaders/TrivialMaterial.hx new file mode 100644 index 00000000..ade7a7a5 --- /dev/null +++ b/src/shaders/TrivialMaterial.hx @@ -0,0 +1,34 @@ +package shaders; + +class TrivialMaterial extends hxsl.Shader { + static var SRC = { + @param var diffuseMap:Sampler2D; + @global var global:{ + @perObject var modelView:Mat4; + @perObject var modelViewInverse:Mat4; + }; + @input var input:{ + var position:Vec3; + var normal:Vec3; + var uv:Vec2; + var t:Vec3; + var b:Vec3; + var n:Vec3; + }; + var calculatedUV:Vec2; + var pixelColor:Vec4; + function vertex() { + calculatedUV = input.uv; + } + function fragment() { + // Diffuse part + var diffuse = diffuseMap.get(calculatedUV); + pixelColor = diffuse * vec4(1.08, 1.03, 0.90, 1); + } + } + + public function new(diffuse) { + super(); + this.diffuseMap = diffuse; + } +} diff --git a/src/shapes/AntiGravity.hx b/src/shapes/AntiGravity.hx index 76962304..181a338d 100644 --- a/src/shapes/AntiGravity.hx +++ b/src/shapes/AntiGravity.hx @@ -16,6 +16,7 @@ class AntiGravity extends PowerUp { this.identifier = "AntiGravity"; this.pickUpName = "Gravity Defier"; this.autoUse = true; + this.useInstancing = true; if (norespawn) this.cooldownDuration = Math.NEGATIVE_INFINITY; } @@ -58,8 +59,8 @@ class AntiGravity extends PowerUp { normalTex.mipMap = Nearest; var shader = new shaders.DefaultMaterial(diffuseTex, normalTex, 32, new h3d.Vector(0.8, 0.8, 0.6, 1), 1); shader.doGammaRamp = false; - var dtsTex = material.mainPass.getShader(shaders.DtsTexture); - dtsTex.passThrough = true; + // var dtsTex = material.mainPass.getShader(shaders.DtsTexture); + // dtsTex.passThrough = true; material.mainPass.removeShader(material.textureShader); material.mainPass.addShader(shader); var thisprops:Dynamic = material.getDefaultProps(); @@ -68,5 +69,18 @@ class AntiGravity extends PowerUp { material.shadows = false; material.receiveShadows = true; } + if (matName == "item_glow") { + var glowpass = material.mainPass.clone(); + glowpass.setPassName("glow"); + glowpass.depthTest = LessEqual; + + material.addPass(glowpass); + material.mainPass.setPassName("glowPre"); + + var thisprops:Dynamic = material.getDefaultProps(); + thisprops.light = false; // We will calculate our own lighting + material.props = thisprops; + material.shadows = false; + } } } diff --git a/src/shapes/Sky.hx b/src/shapes/Sky.hx index fdc52867..968b7b5f 100644 --- a/src/shapes/Sky.hx +++ b/src/shapes/Sky.hx @@ -29,6 +29,7 @@ class Sky extends DtsObject { mat.receiveShadows = false; mat.blendMode = Alpha; mat.mainPass.culling = h3d.mat.Data.Face.None; + mat.mainPass.setPassName("skyshape"); } } }