diff --git a/src/Marble.hx b/src/Marble.hx index 94cef716..612176fa 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -1,5 +1,6 @@ package src; +import shaders.marble.CrystalMarb; import shaders.marble.ClassicMarb; import shapes.HelicopterImage; import shapes.BlastWave; @@ -405,6 +406,12 @@ class Marble extends GameObject { 1); mat.mainPass.addShader(classicGlassShader); } + if (Settings.optionsSettings.marbleShader == "CrystalMarb") { + var marbleNormal = ResourceLoader.getTexture("data/shapes/balls/marble02.normal.png").resource; + marbleNormal.wrap = Repeat; + var classicGlassShader = new CrystalMarb(mat.texture, marbleNormal, this.cubemapRenderer.cubemap, 1); + mat.mainPass.addShader(classicGlassShader); + } var thisprops:Dynamic = mat.getDefaultProps(); thisprops.light = false; // We will calculate our own lighting @@ -1782,7 +1789,8 @@ class Marble extends GameObject { tform.setPosition(new Vector(expectedPos.x, expectedPos.y, expectedPos.z)); this.collider.setTransform(tform); this.velocity = expectedVel; - this.setRotationQuat(this.level.replay.currentPlaybackFrame.marbleOrientation.clone()); + var rQuat = this.level.replay.currentPlaybackFrame.marbleOrientation.clone(); + this.setRotationQuat(rQuat); this.omega = expectedOmega; } diff --git a/src/gui/MarbleSelectGui.hx b/src/gui/MarbleSelectGui.hx index 529c3d09..54a27e42 100644 --- a/src/gui/MarbleSelectGui.hx +++ b/src/gui/MarbleSelectGui.hx @@ -75,37 +75,37 @@ class MarbleSelectGui extends GuiImage { name: "9", dts: "data/shapes/balls/marble02.dts", skin: "base", - shader: "Default" + shader: "CrystalMarb" }, { name: "10", dts: "data/shapes/balls/marble26.dts", skin: "base", - shader: "Default" + shader: "CrystalMarb" }, { name: "11", dts: "data/shapes/balls/marble27.dts", skin: "base", - shader: "Default" + shader: "CrystalMarb" }, { name: "12", dts: "data/shapes/balls/marble28.dts", skin: "base", - shader: "Default" + shader: "CrystalMarb" }, { name: "13", dts: "data/shapes/balls/marble29.dts", skin: "base", - shader: "Default" + shader: "CrystalMarb" }, { name: "14", dts: "data/shapes/balls/marble30.dts", skin: "base", - shader: "Default" + shader: "CrystalMarb" }, { name: "15", diff --git a/src/shaders/marble/ClassicGlass.hx b/src/shaders/marble/ClassicGlass.hx index 99feadd7..8fb12807 100644 --- a/src/shaders/marble/ClassicGlass.hx +++ b/src/shaders/marble/ClassicGlass.hx @@ -17,6 +17,7 @@ class ClassicGlass extends hxsl.Shader { @perObject var modelViewInverse:Mat4; }; @input var input:{ + var position:Vec3; var normal:Vec3; var t:Vec3; var uv:Vec2; @@ -30,7 +31,6 @@ class ClassicGlass extends hxsl.Shader { var pixelTransformedPosition:Vec3; @var var transformedTangent:Vec4; @var var fragLightW:Float; - @var var cubeEyePos:Vec3; function lambert(normal:Vec3, lightPosition:Vec3):Float { var result = dot(normal, lightPosition); return saturate(result); @@ -45,29 +45,18 @@ class ClassicGlass extends hxsl.Shader { calculatedUV = input.uv * uvScaleFactor; var dirLight = vec3(-0.5732, 0.27536, -0.77176); fragLightW = step(-0.5, dot(dirLight, input.normal)); - - var cubeTrans = mat3(global.modelView); - cubeEyePos = camera.position - global.modelView[3].xyz; - cubeEyePos.x *= -1; - cubeEyePos = cubeEyePos.normalize(); } function fragment() { // Diffuse part var texColor = diffuseMap.get(calculatedUV); var bumpColor = normalMap.get(calculatedUV); - var norm = normalize(bumpColor * 2 - 1).xyz; + var norm = normalize(bumpColor.xyz * 2 - 1); + norm.x *= -1; var dirLight = vec4(1.08, 1.03, 0.90, 1); var dirLightDir = vec3(-0.5732, 0.27536, -0.77176); - // Normal - var n = transformedNormal; - var nf = normalize(bumpColor.xyz * 2 - 1); - var tanX = transformedTangent.xyz.normalize(); - var tanY = n.cross(tanX) * transformedTangent.w; - transformedNormal = (nf.x * tanX + nf.y * tanY + nf.z * n).normalize(); - var diffuse = dirLight * (dot(norm, -dirLightDir) + 1.3) * 0.5; // Specular @@ -86,9 +75,9 @@ class ClassicGlass extends hxsl.Shader { var fresnelScale = 1.0; var fresnelTerm = fresnelBias + fresnelScale * (1.0 - fresnelBias) * pow(1.0 - max(dot(viewDir, norm), 0.0), fresnelPow); - var reflectVec = 2 * norm.dot(cubeEyePos) * norm - cubeEyePos * norm.dot(norm); + // var reflectVec = 2 * norm.dot(cubeEyePos) * norm - cubeEyePos * norm.dot(norm); var incidentRay = normalize(pixelTransformedPosition - camera.position); - var reflectionRay = reflect(incidentRay, transformedNormal).normalize(); + var reflectionRay = reflect(incidentRay, norm); var reflectColor = envMap.get(reflectionRay); diff --git a/src/shaders/marble/ClassicMetal.hx b/src/shaders/marble/ClassicMetal.hx index 39d8ec64..16df6741 100644 --- a/src/shaders/marble/ClassicMetal.hx +++ b/src/shaders/marble/ClassicMetal.hx @@ -30,7 +30,6 @@ class ClassicMetal extends hxsl.Shader { var pixelTransformedPosition:Vec3; @var var transformedTangent:Vec4; @var var fragLightW:Float; - @var var cubeEyePos:Vec3; function lambert(normal:Vec3, lightPosition:Vec3):Float { var result = dot(normal, lightPosition); return saturate(result); @@ -42,30 +41,18 @@ class ClassicMetal extends hxsl.Shader { calculatedUV = input.uv * uvScaleFactor; var dirLight = vec3(-0.5732, 0.27536, -0.77176); fragLightW = step(-0.5, dot(dirLight, input.normal)); - - var cubeTrans = mat3(global.modelView); - cubeEyePos = camera.position - global.modelView[3].xyz; - cubeEyePos.x *= -1; - cubeEyePos.x *= -1; - cubeEyePos = cubeEyePos.normalize(); } function fragment() { // Diffuse part var texColor = diffuseMap.get(calculatedUV); var bumpColor = normalMap.get(calculatedUV); - var norm = normalize(bumpColor * 2 - 1).xyz; + var norm = normalize(bumpColor.xyz * 2 - 1); + norm.x *= -1; var dirLight = vec4(1.08, 1.03, 0.90, 1); var dirLightDir = vec3(-0.5732, 0.27536, -0.77176); - // Normal - var n = transformedNormal; - var nf = normalize(bumpColor * 2 - 1); - var tanX = transformedTangent.xyz.normalize(); - var tanY = n.cross(tanX) * transformedTangent.w; - transformedNormal = (nf.x * tanX + nf.y * tanY + nf.z * n).normalize(); - var diffuse = dirLight * (dot(norm, -dirLightDir) + 1.3) * 0.5; // Specular @@ -76,7 +63,7 @@ class ClassicMetal extends hxsl.Shader { var viewDir = normalize(camera.position - pixelTransformedPosition); - norm = norm * mat3(global.modelView); + norm = (norm * mat3(global.modelView)).normalize(); // Fresnel var fresnelBias = 0.0; @@ -84,12 +71,12 @@ class ClassicMetal extends hxsl.Shader { var fresnelScale = 1.0; var fresnelTerm = fresnelBias + fresnelScale * (1.0 - fresnelBias) * pow(1.0 - max(dot(viewDir, norm), 0.0), fresnelPow); - var reflectVec = 2 * norm.dot(cubeEyePos) * norm - cubeEyePos * norm.dot(norm); + // var reflectVec = 2 * norm.dot(cubeEyePos) * norm - cubeEyePos * norm.dot(norm); var incidentRay = normalize(pixelTransformedPosition - camera.position); var reflectionRay = reflect(incidentRay, norm); - var reflectColor = envMap.get(reflectVec); + var reflectColor = envMap.get(reflectionRay); var finalReflectColor = vec4((reflectColor.r + reflectColor.g + reflectColor.b) / 3.0); var outCol = texColor * mix(vec4(1), finalReflectColor, bumpColor.a); diff --git a/src/shaders/marble/CrystalMarb.hx b/src/shaders/marble/CrystalMarb.hx new file mode 100644 index 00000000..8cf7b36f --- /dev/null +++ b/src/shaders/marble/CrystalMarb.hx @@ -0,0 +1,89 @@ +package shaders.marble; + +class CrystalMarb extends hxsl.Shader { + static var SRC = { + @param var diffuseMap:Sampler2D; + @param var normalMap:Sampler2D; + @param var envMap:SamplerCube; + @param var uvScaleFactor:Float; + @global var camera:{ + var position:Vec3; + @var var dir:Vec3; + }; + @global var global:{ + @perObject var modelView:Mat4; + @perObject var modelViewInverse:Mat4; + }; + @input var input:{ + var position:Vec3; + var normal:Vec3; + var t:Vec3; + var uv:Vec2; + }; + var calculatedUV:Vec2; + var pixelColor:Vec4; + var specColor:Vec3; + var specPower:Float; + var transformedPosition:Vec3; + var transformedNormal:Vec3; + var pixelTransformedPosition:Vec3; + @var var transformedTangent:Vec4; + function lambert(normal:Vec3, lightPosition:Vec3):Float { + var result = dot(normal, lightPosition); + return saturate(result); + } + function transposeMat3(m:Mat3):Mat3 { + return mat3(vec3(m[0].x, m[1].x, m[2].x), vec3(m[0].y, m[1].y, m[2].y), vec3(m[0].z, m[1].z, m[2].z)); + } + function refract(incident:Vec3, normal:Vec3, eta:Float):Vec3 { + var ndoti = dot(normal, incident); + var k = 1.0 - eta * eta * (1.0 - ndoti * ndoti); + return k < 0.0 ? vec3(0.0) : eta * incident - (eta * ndoti + sqrt(k)) * normal; + } + function __init__vertex() { + transformedTangent = vec4(input.t * global.modelView.mat3(), input.t.dot(input.t) > 0.5 ? 1. : -1.); + } + function vertex() { + calculatedUV = input.uv * uvScaleFactor; + var dirLight = vec3(-0.5732, 0.27536, -0.77176); + } + function fragment() { + // Diffuse part + var texColor = diffuseMap.get(calculatedUV); + var bumpColor = normalMap.get(calculatedUV); + + var norm = normalize(bumpColor.xyz * 2 - 1); + norm.x *= -1; + + var viewDir = normalize(camera.position - pixelTransformedPosition); + + norm = (norm * mat3(global.modelView)).normalize(); + + // Fresnel + var fresnelBias = 0.2; + var fresnelPow = 1.3; + var fresnelScale = 1.0; + var fresnelTerm = fresnelBias + fresnelScale * (1.0 - fresnelBias) * pow(1.0 - max(dot(viewDir, norm), 0.0), fresnelPow); + + // var reflectVec = 2 * norm.dot(cubeEyePos) * norm - cubeEyePos * norm.dot(norm); + var incidentRay = normalize(pixelTransformedPosition - camera.position); + var reflectionRay = reflect(incidentRay, norm); + var refractVec = refract(-incidentRay, norm, 1); + + var reflectColor = envMap.get(reflectionRay); + var refractColor = envMap.get(refractVec); + + var outCol = mix(texColor, vec4(1), 0.25) * mix(refractColor, reflectColor, fresnelTerm); + + pixelColor = outCol; + } + } + + public function new(diffuse, normal, skybox, uvScaleFactor) { + super(); + this.diffuseMap = diffuse; + this.normalMap = normal; + this.envMap = skybox; + this.uvScaleFactor = uvScaleFactor; + } +}