diff --git a/away3d/materials/MaterialBase.hx b/away3d/materials/MaterialBase.hx index 6236c33..23146c6 100644 --- a/away3d/materials/MaterialBase.hx +++ b/away3d/materials/MaterialBase.hx @@ -1,3 +1,4 @@ +/** /** * MaterialBase forms an abstract base class for any material. * A material consists of several passes, each of which constitutes at least one render call. Several passes could @@ -39,6 +40,7 @@ class MaterialBase extends NamedAssetBase implements IAsset { public var smooth(get_smooth, set_smooth):Bool; public var depthCompareMode(get_depthCompareMode, set_depthCompareMode):Context3DCompareMode; public var repeat(get_repeat, set_repeat):Bool; + public var maxAnisotropy(get_maxAnisotropy, set_maxAnisotropy):Float; public var bothSides(get_bothSides, set_bothSides):Bool; public var blendMode(get_blendMode, set_blendMode):BlendMode; public var alphaPremultiplied(get_alphaPremultiplied, set_alphaPremultiplied):Bool; @@ -97,6 +99,7 @@ class MaterialBase extends NamedAssetBase implements IAsset { private var _mipmap:Bool; private var _smooth:Bool; private var _repeat:Bool; + private var _maxAnisotropy:Float; private var _depthPass:DepthMapPass; private var _distancePass:DistanceMapPass; private var _lightPicker:LightPickerBase; @@ -110,6 +113,7 @@ class MaterialBase extends NamedAssetBase implements IAsset { _blendMode = BlendMode.NORMAL; _mipmap = true; _smooth = true; + _maxAnisotropy = 1; _depthCompareMode = Context3DCompareMode.LESS_EQUAL; _owners = new Array(); _passes = new Array(); @@ -222,6 +226,23 @@ class MaterialBase extends NamedAssetBase implements IAsset { return value; } + /** + * Indicates the number of Anisotropic filtering samples to take for mipmapping + */ + public function get_maxAnisotropy():Float { + return _maxAnisotropy; + } + + public function set_maxAnisotropy(value:Float):Float { + _maxAnisotropy = value; + var i:Int = 0; + while (i < _numPasses) { + _passes[i].maxAnisotropy = maxAnisotropy; + ++i; + } + return maxAnisotropy; + } + /** * Cleans up resources owned by the material, including passes. Textures are not owned by the material since they * could be used by other materials and will not be disposed. @@ -594,6 +615,7 @@ class MaterialBase extends NamedAssetBase implements IAsset { pass.mipmap = _mipmap; pass.smooth = _smooth; pass.repeat = _repeat; + pass.maxAnisotropy = _maxAnisotropy; pass.lightPicker = _lightPicker; pass.bothSides = _bothSides; pass.addEventListener(Event.CHANGE, onPassChange); diff --git a/away3d/materials/TextureMaterial.hx b/away3d/materials/TextureMaterial.hx index d6f21dd..7834f2f 100644 --- a/away3d/materials/TextureMaterial.hx +++ b/away3d/materials/TextureMaterial.hx @@ -6,6 +6,7 @@ package away3d.materials; import openfl.display.BlendMode; import openfl.geom.ColorTransform; import away3d.textures.Texture2DBase; + class TextureMaterial extends SinglePassMaterialBase { public var animateUVs(get_animateUVs, set_animateUVs):Bool; public var alpha(get_alpha, set_alpha):Float; @@ -18,13 +19,15 @@ class TextureMaterial extends SinglePassMaterialBase { * @param smooth Indicates whether the texture should be filtered when sampled. Defaults to true. * @param repeat Indicates whether the texture should be tiled when sampled. Defaults to true. * @param mipmap Indicates whether or not any used textures should use mipmapping. Defaults to true. - */ - public function new(texture:Texture2DBase = null, smooth:Bool = true, repeat:Bool = false, mipmap:Bool = true) { + * @param maxAnisotropy Indicates the number of samples to use if Anisotropic mipmap filtering is applied + */ + public function new(texture:Texture2DBase = null, smooth:Bool = true, repeat:Bool = false, mipmap:Bool = true, maxAnisotropy:Float = 1) { super(); this.texture = texture; this.smooth = smooth; this.repeat = repeat; this.mipmap = mipmap; + this.maxAnisotropy = maxAnisotropy; } /** diff --git a/away3d/materials/TextureMultiPassMaterial.hx b/away3d/materials/TextureMultiPassMaterial.hx index a5f2fa4..9442f2e 100644 --- a/away3d/materials/TextureMultiPassMaterial.hx +++ b/away3d/materials/TextureMultiPassMaterial.hx @@ -5,7 +5,6 @@ package away3d.materials; import away3d.textures.Texture2DBase; - class TextureMultiPassMaterial extends MultiPassMaterialBase { public var animateUVs(get_animateUVs, set_animateUVs):Bool; public var texture(get_texture, set_texture):Texture2DBase; @@ -19,13 +18,15 @@ class TextureMultiPassMaterial extends MultiPassMaterialBase { * @param smooth Indicates whether the texture should be filtered when sampled. Defaults to true. * @param repeat Indicates whether the texture should be tiled when sampled. Defaults to true. * @param mipmap Indicates whether or not any used textures should use mipmapping. Defaults to true. - */ - public function new(texture:Texture2DBase = null, smooth:Bool = true, repeat:Bool = false, mipmap:Bool = true) { + * @param maxAnisotropy Indicates the number of samples to use if Anisotropic mipmap filtering is applied + */ + public function new(texture:Texture2DBase = null, smooth:Bool = true, repeat:Bool = false, mipmap:Bool = true, maxAnisotropy:Float = 1) { super(); this.texture = texture; this.smooth = smooth; this.repeat = repeat; this.mipmap = mipmap; + this.maxAnisotropy = maxAnisotropy; } /** diff --git a/away3d/materials/compilation/ShaderCompiler.hx b/away3d/materials/compilation/ShaderCompiler.hx index 3f7676c..7560904 100644 --- a/away3d/materials/compilation/ShaderCompiler.hx +++ b/away3d/materials/compilation/ShaderCompiler.hx @@ -66,6 +66,7 @@ class ShaderCompiler { private var _smooth:Bool; private var _repeat:Bool; private var _mipmap:Bool; + private var _maxAnisotropy:Float; private var _enableLightFallOff:Bool; private var _preserveAlpha:Bool; private var _animateUVs:Bool; @@ -230,10 +231,11 @@ class ShaderCompiler { * @param repeat Indicates whether the texture should be tiled when sampled. Defaults to true. * @param mipmap Indicates whether or not any used textures should use mipmapping. Defaults to true. */ - public function setTextureSampling(smooth:Bool, repeat:Bool, mipmap:Bool):Void { + public function setTextureSampling(smooth:Bool, repeat:Bool, mipmap:Bool, maxAnisotropy:Float = 1):Void { _smooth = smooth; _repeat = repeat; _mipmap = mipmap; + _maxAnisotropy = maxAnisotropy; } /** @@ -477,6 +479,7 @@ class ShaderCompiler { methodVO.useSmoothTextures = _smooth; methodVO.repeatTextures = _repeat; methodVO.useMipmapping = _mipmap; + methodVO.maxAnisotropy = _maxAnisotropy; methodVO.useLightFallOff = _enableLightFallOff && _profile != "baselineConstrained"; methodVO.numLights = _numLights + _numLightProbes; method.initVO(methodVO); diff --git a/away3d/materials/methods/BasicAmbientMethod.hx b/away3d/materials/methods/BasicAmbientMethod.hx index 4251481..15e1520 100644 --- a/away3d/materials/methods/BasicAmbientMethod.hx +++ b/away3d/materials/methods/BasicAmbientMethod.hx @@ -148,7 +148,7 @@ class BasicAmbientMethod extends ShadingMethodBase { override public function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):Void { if (_useTexture) { #if !flash - stage3DProxy._context3D.setSamplerStateAt(vo.texturesIndex, vo.repeatTextures ? Context3DWrapMode.REPEAT : Context3DWrapMode.CLAMP, vo.useSmoothTextures ? Context3DTextureFilter.LINEAR : Context3DTextureFilter.NEAREST, vo.useMipmapping ? Context3DMipFilter.MIPLINEAR : Context3DMipFilter.MIPNONE); + stage3DProxy._context3D.setSamplerStateAt(vo.texturesIndex, vo.repeatTextures ? Context3DWrapMode.REPEAT : Context3DWrapMode.CLAMP, vo.useSmoothTextures ? Context3DTextureFilter.LINEAR : Context3DTextureFilter.NEAREST, vo.useMipmapping ? Context3DMipFilter.MIPLINEAR : Context3DMipFilter.MIPNONE, vo.maxAnisotropy ); #end stage3DProxy._context3D.setTextureAt(vo.texturesIndex, _texture.getTextureForStage3D(stage3DProxy)); } diff --git a/away3d/materials/methods/BasicDiffuseMethod.hx b/away3d/materials/methods/BasicDiffuseMethod.hx index 9b17b4e..613d740 100644 --- a/away3d/materials/methods/BasicDiffuseMethod.hx +++ b/away3d/materials/methods/BasicDiffuseMethod.hx @@ -299,7 +299,7 @@ class BasicDiffuseMethod extends LightingMethodBase { override public function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):Void { if (_useTexture) { #if !flash - stage3DProxy._context3D.setSamplerStateAt(vo.texturesIndex, vo.repeatTextures ? Context3DWrapMode.REPEAT : Context3DWrapMode.CLAMP, vo.useSmoothTextures ? Context3DTextureFilter.LINEAR : Context3DTextureFilter.NEAREST, vo.useMipmapping ? Context3DMipFilter.MIPLINEAR : Context3DMipFilter.MIPNONE); + stage3DProxy._context3D.setSamplerStateAt(vo.texturesIndex, vo.repeatTextures ? Context3DWrapMode.REPEAT : Context3DWrapMode.CLAMP, vo.useSmoothTextures ? Context3DTextureFilter.LINEAR : Context3DTextureFilter.NEAREST, vo.useMipmapping ? Context3DMipFilter.MIPLINEAR : Context3DMipFilter.MIPNONE, vo.maxAnisotropy ); #end stage3DProxy._context3D.setTextureAt(vo.texturesIndex, _texture.getTextureForStage3D(stage3DProxy)); if (_alphaThreshold > 0) vo.fragmentData[vo.fragmentConstantsIndex] = _alphaThreshold; diff --git a/away3d/materials/methods/BasicNormalMethod.hx b/away3d/materials/methods/BasicNormalMethod.hx index 9b54cc0..a39930b 100644 --- a/away3d/materials/methods/BasicNormalMethod.hx +++ b/away3d/materials/methods/BasicNormalMethod.hx @@ -96,7 +96,7 @@ class BasicNormalMethod extends ShadingMethodBase { override public function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):Void { if (vo.texturesIndex >= 0) { #if !flash - stage3DProxy._context3D.setSamplerStateAt(vo.texturesIndex, vo.repeatTextures ? Context3DWrapMode.REPEAT : Context3DWrapMode.CLAMP, vo.useSmoothTextures ? Context3DTextureFilter.LINEAR : Context3DTextureFilter.NEAREST, vo.useMipmapping ? Context3DMipFilter.MIPLINEAR : Context3DMipFilter.MIPNONE); + stage3DProxy._context3D.setSamplerStateAt(vo.texturesIndex, vo.repeatTextures ? Context3DWrapMode.REPEAT : Context3DWrapMode.CLAMP, vo.useSmoothTextures ? Context3DTextureFilter.LINEAR : Context3DTextureFilter.NEAREST, vo.useMipmapping ? Context3DMipFilter.MIPLINEAR : Context3DMipFilter.MIPNONE, vo.maxAnisotropy ); #end stage3DProxy._context3D.setTextureAt(vo.texturesIndex, _texture.getTextureForStage3D(stage3DProxy)); } diff --git a/away3d/materials/methods/BasicSpecularMethod.hx b/away3d/materials/methods/BasicSpecularMethod.hx index 74b1a2b..cc71b91 100644 --- a/away3d/materials/methods/BasicSpecularMethod.hx +++ b/away3d/materials/methods/BasicSpecularMethod.hx @@ -177,15 +177,15 @@ class BasicSpecularMethod extends LightingMethodBase { var viewDirReg:ShaderRegisterElement = _sharedRegisters.viewDirFragment; var normalReg:ShaderRegisterElement = _sharedRegisters.normalFragment; -// blinn-phong half vector model + // blinn-phong half vector model code += "add " + t + ", " + lightDirReg + ", " + viewDirReg + "\n" + "nrm " + t + ".xyz, " + t + "\n" + "dp3 " + t + ".w, " + normalReg + ", " + t + "\n" + "sat " + t + ".w, " + t + ".w\n"; if (_useTexture) { -// apply gloss modulation from texture + // apply gloss modulation from texture code += "mul " + _specularTexData + ".w, " + _specularTexData + ".y, " + _specularDataRegister + ".w\n" + "pow " + t + ".w, " + t + ".w, " + _specularTexData + ".w\n"; } else code += "pow " + t + ".w, " + t + ".w, " + _specularDataRegister + ".w\n"; -// attenuate + // attenuate if (vo.useLightFallOff) code += "mul " + t + ".w, " + t + ".w, " + lightDirReg + ".w\n"; if (_modulateMethod != null) code += _modulateMethod(vo, t, regCache, _sharedRegisters); code += "mul " + t + ".xyz, " + lightColReg + ", " + t + ".w\n"; @@ -204,7 +204,7 @@ class BasicSpecularMethod extends LightingMethodBase { override public function getFragmentCodePerProbe(vo:MethodVO, cubeMapReg:ShaderRegisterElement, weightRegister:String, regCache:ShaderRegisterCache):String { var code:String = ""; var t:ShaderRegisterElement; -// write in temporary if not first light, so we can add to total diffuse colour + // write in temporary if not first light, so we can add to total diffuse colour if (_isFirstLight) t = _totalLightColorReg else { t = regCache.getFreeFragmentVectorTemp(); @@ -231,7 +231,7 @@ class BasicSpecularMethod extends LightingMethodBase { if (vo.numLights == 0) return code; if (_shadowRegister != null) code += "mul " + _totalLightColorReg + ".xyz, " + _totalLightColorReg + ", " + _shadowRegister + ".w\n"; if (_useTexture) { -// apply strength modulation from texture + // apply strength modulation from texture code += "mul " + _totalLightColorReg + ".xyz, " + _totalLightColorReg + ", " + _specularTexData + ".x\n"; regCache.removeFragmentTempUsage(_specularTexData); } @@ -244,11 +244,11 @@ class BasicSpecularMethod extends LightingMethodBase { * @inheritDoc */ override public function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):Void { -//var context : Context3D = stage3DProxy._context3D; + //var context : Context3D = stage3DProxy._context3D; if (vo.numLights == 0) return; if (_useTexture) { #if !flash - stage3DProxy._context3D.setSamplerStateAt(vo.texturesIndex, vo.repeatTextures ? Context3DWrapMode.REPEAT : Context3DWrapMode.CLAMP, vo.useSmoothTextures ? Context3DTextureFilter.LINEAR : Context3DTextureFilter.NEAREST, vo.useMipmapping ? Context3DMipFilter.MIPLINEAR : Context3DMipFilter.MIPNONE); + stage3DProxy._context3D.setSamplerStateAt(vo.texturesIndex, vo.repeatTextures ? Context3DWrapMode.REPEAT : Context3DWrapMode.CLAMP, vo.useSmoothTextures ? Context3DTextureFilter.LINEAR : Context3DTextureFilter.NEAREST, vo.useMipmapping ? Context3DMipFilter.MIPLINEAR : Context3DMipFilter.MIPNONE, vo.maxAnisotropy ); #end stage3DProxy._context3D.setTextureAt(vo.texturesIndex, _texture.getTextureForStage3D(stage3DProxy)); } diff --git a/away3d/materials/methods/MethodVO.hx b/away3d/materials/methods/MethodVO.hx index 9956e60..f0b7aff 100644 --- a/away3d/materials/methods/MethodVO.hx +++ b/away3d/materials/methods/MethodVO.hx @@ -23,6 +23,7 @@ class MethodVO { public var useMipmapping:Bool; public var useSmoothTextures:Bool; public var repeatTextures:Bool; + public var maxAnisotropy:Float; // internal stuff for the material to know before assembling code public var needsProjection:Bool; public var needsView:Bool; @@ -50,6 +51,7 @@ class MethodVO { vertexConstantsIndex = -1; fragmentConstantsIndex = -1; useMipmapping = true; + maxAnisotropy = 1; useSmoothTextures = true; repeatTextures = false; needsProjection = false; diff --git a/away3d/materials/passes/CompiledPass.hx b/away3d/materials/passes/CompiledPass.hx index 85fc3e6..8b74949 100644 --- a/away3d/materials/passes/CompiledPass.hx +++ b/away3d/materials/passes/CompiledPass.hx @@ -209,7 +209,7 @@ class CompiledPass extends MaterialPassBase { _compiler.methodSetup = _methodSetup; _compiler.diffuseLightSources = _diffuseLightSources; _compiler.specularLightSources = _specularLightSources; - _compiler.setTextureSampling(_smooth, _repeat, _mipmap); + _compiler.setTextureSampling(_smooth, _repeat, _mipmap, _maxAnisotropy); _compiler.setConstantDataBuffers(_vertexConstantData, _fragmentConstantData); _compiler.animateUVs = _animateUVs; _compiler.alphaPremultiplied = _alphaPremultiplied && _enableBlending; @@ -302,6 +302,15 @@ class CompiledPass extends MaterialPassBase { return value; } + /** + * @inheritDoc + */ + override public function set_maxAnisotropy(value:Float):Float { + if (_maxAnisotropy == value) return value; + super.maxAnisotropy = value; + return value; + } + /** * The normal map to modulate the direction of the surface for each texel. The default normal method expects * tangent-space normal maps, but others could expect object-space maps. diff --git a/away3d/materials/passes/MaterialPassBase.hx b/away3d/materials/passes/MaterialPassBase.hx index ad82f51..e43a5a5 100644 --- a/away3d/materials/passes/MaterialPassBase.hx +++ b/away3d/materials/passes/MaterialPassBase.hx @@ -31,6 +31,7 @@ class MaterialPassBase extends EventDispatcher { public var mipmap(get_mipmap, set_mipmap):Bool; public var smooth(get_smooth, set_smooth):Bool; public var repeat(get_repeat, set_repeat):Bool; + public var maxAnisotropy(get_maxAnisotropy, set_maxAnisotropy):Float; public var bothSides(get_bothSides, set_bothSides):Bool; public var depthCompareMode(get_depthCompareMode, set_depthCompareMode):Context3DCompareMode; public var animationSet(get_animationSet, set_animationSet):IAnimationSet; @@ -60,6 +61,7 @@ class MaterialPassBase extends EventDispatcher { private var _smooth:Bool; private var _repeat:Bool; private var _mipmap:Bool; + private var _maxAnisotropy:Float; private var _depthCompareMode:Context3DCompareMode; private var _blendFactorSource:Context3DBlendFactor; private var _blendFactorDest:Context3DBlendFactor; @@ -105,6 +107,7 @@ class MaterialPassBase extends EventDispatcher { _smooth = true; _repeat = false; _mipmap = true; + _maxAnisotropy = 1; _depthCompareMode = Context3DCompareMode.LESS_EQUAL; _blendFactorSource = Context3DBlendFactor.ONE; @@ -168,6 +171,21 @@ class MaterialPassBase extends EventDispatcher { return _mipmap; } + /** + * Indicates the number of Anisotropic filtering samples to take for mipmapping + */ + public function get_maxAnisotropy():Float { + return _maxAnisotropy; + } + + public function set_maxAnisotropy(value:Float):Float { + if (_maxAnisotropy == value) + return _maxAnisotropy; + _maxAnisotropy = value; + invalidateShaderProgram(); + return maxAnisotropy; + } + /** * Defines whether smoothing should be applied to any used textures. */ diff --git a/away3d/textures/BitmapTexture.hx b/away3d/textures/BitmapTexture.hx index cc6a5d7..b78ee19 100644 --- a/away3d/textures/BitmapTexture.hx +++ b/away3d/textures/BitmapTexture.hx @@ -40,7 +40,7 @@ class BitmapTexture extends Texture2DBase { } override private function uploadContent(texture:TextureBase):Void { - #if (flash || html5) + #if flash if (_generateMipmaps) MipmapGenerator.generateMipMaps(_bitmapData, texture, _mipMapHolder, true) else cast((texture), Texture).uploadFromBitmapData(_bitmapData, 0); #else diff --git a/away3d/textures/RenderCubeTexture.hx b/away3d/textures/RenderCubeTexture.hx index 9ee05fe..ac5b8d6 100644 --- a/away3d/textures/RenderCubeTexture.hx +++ b/away3d/textures/RenderCubeTexture.hx @@ -31,7 +31,7 @@ class RenderCubeTexture extends CubeTextureBase { var bmd:BitmapData = new BitmapData(_width, _height, false, 0); var i:Int = 0; while (i < 6) { - #if (flash || html5) + #if flash MipmapGenerator.generateMipMaps(bmd, texture, null, false, i); #else cast((texture), CubeTexture).uploadFromBitmapData(bmd, i, 0); diff --git a/backends/html5/openfl/display3D/Context3D.hx b/backends/html5/openfl/display3D/Context3D.hx index 973bdd8..0703dea 100755 --- a/backends/html5/openfl/display3D/Context3D.hx +++ b/backends/html5/openfl/display3D/Context3D.hx @@ -60,6 +60,7 @@ class Context3D private var samplerParameters :Array; //TODO : use Tupple3 private var scrollRect:Rectangle; + public static var MAX_SAMPLERS:Int = 8; public function new() @@ -74,7 +75,8 @@ class Context3D this.samplerParameters[ i ] = new SamplerState(); this.samplerParameters[ i ].wrap = Context3DWrapMode.REPEAT; this.samplerParameters[ i ].filter = Context3DTextureFilter.LINEAR; - this.samplerParameters[ i ].mipfilter =Context3DMipFilter.MIPNONE; + this.samplerParameters[ i ].mipfilter = Context3DMipFilter.MIPNONE; + this.samplerParameters[ i ].maxAnisotropy = 1; } var stage = Lib.current.stage; @@ -413,7 +415,7 @@ class Context3D GL.viewport(0, 0, texture.width, texture.height); } - public function setSamplerStateAt(sampler:Int, wrap:Context3DWrapMode, filter:Context3DTextureFilter, mipfilter:Context3DMipFilter):Void + public function setSamplerStateAt(sampler:Int, wrap:Context3DWrapMode, filter:Context3DTextureFilter, mipfilter:Context3DMipFilter, maxAnisotropy:Float = 1 ):Void { //TODO for flash < 11.6 : patch the AGAL (using specific opcodes) and rebuild the program? @@ -421,12 +423,13 @@ class Context3D this.samplerParameters[ sampler ].wrap = wrap; this.samplerParameters[ sampler ].filter = filter; this.samplerParameters[ sampler ].mipfilter = mipfilter; + this.samplerParameters[ sampler ].maxAnisotropy = maxAnisotropy; } else { throw "Sampler is out of bounds."; } } - private function setTextureParameters(texture : TextureBase, wrap : Context3DWrapMode, filter : Context3DTextureFilter, mipfilter : Context3DMipFilter):Void{ + private function setTextureParameters(texture : TextureBase, wrap : Context3DWrapMode, filter : Context3DTextureFilter, mipfilter : Context3DMipFilter, maxAnisotropy:Float = 1 ):Void{ if (Std.is (texture, openfl.display3D.textures.Texture)) { @@ -450,11 +453,37 @@ class Context3D //TODO CHECK the mipmap filters switch(mipfilter){ case Context3DMipFilter.MIPLINEAR: + GL.generateMipmap(GL.TEXTURE_2D); GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR_MIPMAP_LINEAR); + var ext = GL.getExtension("EXT_texture_filter_anisotropic") || GL.getExtension("MOZ_EXT_texture_filter_anisotropic") || GL.getExtension("WEBKIT_EXT_texture_filter_anisotropic"); + if (ext!=null) { + // I found that setting the filtering to a higher level then querying the texParameter + // returns the maximum capability for the device (as far as I can tell) + GL.texParameterf(GL.TEXTURE_2D, 0x84FE, maxAnisotropy); + var actualMaxAnisotropy = GL.getTexParameter(GL.TEXTURE_2D, 0x84FE); + + // Currently hard coded 0x84FE as the GL.TEXTURE_MAX_ANISOTROPY_EXT enum + // GL.texParameterf(GL_TEXTURE_2D, GL.TEXTURE_MAX_ANISOTROPY_EXT, 8.0); + GL.texParameterf(GL.TEXTURE_2D, 0x84FE, (actualMaxAnisotropy < maxAnisotropy) ? actualMaxAnisotropy : maxAnisotropy ); + } + case Context3DMipFilter.MIPNEAREST: + GL.generateMipmap(GL.TEXTURE_2D); GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST_MIPMAP_NEAREST); + var ext = GL.getExtension("EXT_texture_filter_anisotropic") || GL.getExtension("MOZ_EXT_texture_filter_anisotropic") || GL.getExtension("WEBKIT_EXT_texture_filter_anisotropic"); + if (ext!=null) { + // I found that setting the filtering to a higher level then querying the texParameter + // returns the maximum capability for the device (as far as I can tell) + GL.texParameterf(GL.TEXTURE_2D, 0x84FE, maxAnisotropy); + var actualMaxAnisotropy = GL.getTexParameter(GL.TEXTURE_2D, 0x84FE); + + // Currently hard coded 0x84FE as the GL.TEXTURE_MAX_ANISOTROPY_EXT enum + // GL.texParameterf(GL_TEXTURE_2D, GL.TEXTURE_MAX_ANISOTROPY_EXT, 8.0); + GL.texParameterf(GL.TEXTURE_2D, 0x84FE, (actualMaxAnisotropy < maxAnisotropy) ? actualMaxAnisotropy : maxAnisotropy ); + } + case Context3DMipFilter.MIPNONE: GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); } @@ -580,9 +609,9 @@ class Context3D var parameters:SamplerState= samplerParameters[textureIndex]; if (parameters != null) { - setTextureParameters(texture, parameters.wrap, parameters.filter, parameters.mipfilter); + setTextureParameters(texture, parameters.wrap, parameters.filter, parameters.mipfilter, parameters.maxAnisotropy); } else { - setTextureParameters(texture, Context3DWrapMode.REPEAT, Context3DTextureFilter.NEAREST, Context3DMipFilter.MIPNONE); + setTextureParameters(texture, Context3DWrapMode.REPEAT, Context3DTextureFilter.NEAREST, Context3DMipFilter.MIPNONE, 1); } } diff --git a/backends/html5/openfl/display3D/SamplerState.hx b/backends/html5/openfl/display3D/SamplerState.hx index d440e6b..da40969 100755 --- a/backends/html5/openfl/display3D/SamplerState.hx +++ b/backends/html5/openfl/display3D/SamplerState.hx @@ -5,6 +5,8 @@ class SamplerState public var wrap:Context3DWrapMode ; public var filter:Context3DTextureFilter ; public var mipfilter:Context3DMipFilter ; + public var maxAnisotropy:Float ; + public function new():Void { } diff --git a/backends/native/openfl/display3D/Context3D.hx b/backends/native/openfl/display3D/Context3D.hx index 96bfbbb..4fa6673 100755 --- a/backends/native/openfl/display3D/Context3D.hx +++ b/backends/native/openfl/display3D/Context3D.hx @@ -60,6 +60,7 @@ class Context3D private var samplerParameters :Array; //TODO : use Tupple3 private var scrollRect:Rectangle; + public static var MAX_SAMPLERS:Int = 8; public function new() @@ -75,6 +76,7 @@ class Context3D this.samplerParameters[ i ].wrap = Context3DWrapMode.REPEAT; this.samplerParameters[ i ].filter = Context3DTextureFilter.LINEAR; this.samplerParameters[ i ].mipfilter =Context3DMipFilter.MIPNONE; + this.samplerParameters[ i ].maxAnisotropy = 1; } var stage = Lib.current.stage; @@ -409,20 +411,21 @@ class Context3D GL.viewport(0, 0, texture.width, texture.height); } - public function setSamplerStateAt(sampler:Int, wrap:Context3DWrapMode, filter:Context3DTextureFilter, mipfilter:Context3DMipFilter):Void + public function setSamplerStateAt(sampler:Int, wrap:Context3DWrapMode, filter:Context3DTextureFilter, mipfilter:Context3DMipFilter, maxAnisotropy:Float = 1 ):Void { //TODO for flash < 11.6 : patch the AGAL (using specific opcodes) and rebuild the program? if (0 <= sampler && sampler < MAX_SAMPLERS) { this.samplerParameters[ sampler ].wrap = wrap; this.samplerParameters[ sampler ].filter = filter; - this.samplerParameters[ sampler ].mipfilter = mipfilter; + this.samplerParameters[ sampler ].mipfilter = mipfilter; + this.samplerParameters[ sampler ].maxAnisotropy = maxAnisotropy; } else { throw "Sampler is out of bounds."; } } - private function setTextureParameters(texture : TextureBase, wrap : Context3DWrapMode, filter : Context3DTextureFilter, mipfilter : Context3DMipFilter):Void{ + private function setTextureParameters(texture : TextureBase, wrap : Context3DWrapMode, filter : Context3DTextureFilter, mipfilter : Context3DMipFilter, maxAnisotropy:Float = 1 ):Void{ if (Std.is (texture, openfl.display3D.textures.Texture)) { @@ -449,14 +452,32 @@ class Context3D case Context3DMipFilter.MIPLINEAR: GL.generateMipmap(GL.TEXTURE_2D); GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR_MIPMAP_LINEAR); - //GL.texParameterf(GL_TEXTURE_2D, GL.TEXTURE_MAX_ANISOTROPY_EXT, 8.0); - GL.texParameterf(GL.TEXTURE_2D, 0x84FE, 8.0); + if (GL.getSupportedExtensions().indexOf("GL_EXT_texture_filter_anisotropic")!=-1) { + // I found that setting the filtering to a higher level then querying the texParameter + // returns the maximum capability for the device (as far as I can tell) + GL.texParameterf(GL.TEXTURE_2D, 0x84FE, maxAnisotropy); + var actualMaxAnisotropy = GL.getTexParameter(GL.TEXTURE_2D, 0x84FE); + + // Currently hard coded 0x84FE as the GL.TEXTURE_MAX_ANISOTROPY_EXT enum + // GL.texParameterf(GL_TEXTURE_2D, GL.TEXTURE_MAX_ANISOTROPY_EXT, 8.0); + GL.texParameterf(GL.TEXTURE_2D, 0x84FE, (actualMaxAnisotropy < maxAnisotropy) ? actualMaxAnisotropy : maxAnisotropy ); + } + case Context3DMipFilter.MIPNEAREST: GL.generateMipmap(GL.TEXTURE_2D); GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST_MIPMAP_NEAREST); - //GL.texParameterf(GL_TEXTURE_2D, GL.TEXTURE_MAX_ANISOTROPY_EXT, 8.0); - GL.texParameterf(GL.TEXTURE_2D, 0x84FE, 8.0); + + if (GL.getSupportedExtensions().indexOf("GL_EXT_texture_filter_anisotropic")!=-1) { + // I found that setting the filtering to a higher level then querying the texParameter + // returns the maximum capability for the device (as far as I can tell) + GL.texParameterf(GL.TEXTURE_2D, 0x84FE, maxAnisotropy); + var actualMaxAnisotropy = GL.getTexParameter(GL.TEXTURE_2D, 0x84FE); + + // Currently hard coded 0x84FE as the GL.TEXTURE_MAX_ANISOTROPY_EXT enum + // GL.texParameterf(GL_TEXTURE_2D, GL.TEXTURE_MAX_ANISOTROPY_EXT, 8.0); + GL.texParameterf(GL.TEXTURE_2D, 0x84FE, (actualMaxAnisotropy < maxAnisotropy) ? actualMaxAnisotropy : maxAnisotropy ); + } case Context3DMipFilter.MIPNONE: GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); @@ -586,9 +607,9 @@ class Context3D var parameters:SamplerState= samplerParameters[textureIndex]; if (parameters != null) { - setTextureParameters(texture, parameters.wrap, parameters.filter, parameters.mipfilter); + setTextureParameters(texture, parameters.wrap, parameters.filter, parameters.mipfilter, parameters.maxAnisotropy); } else { - setTextureParameters(texture, Context3DWrapMode.REPEAT, Context3DTextureFilter.NEAREST, Context3DMipFilter.MIPNONE); + setTextureParameters(texture, Context3DWrapMode.REPEAT, Context3DTextureFilter.NEAREST, Context3DMipFilter.MIPNONE, 1); } } diff --git a/backends/native/openfl/display3D/SamplerState.hx b/backends/native/openfl/display3D/SamplerState.hx index d440e6b..da40969 100755 --- a/backends/native/openfl/display3D/SamplerState.hx +++ b/backends/native/openfl/display3D/SamplerState.hx @@ -5,6 +5,8 @@ class SamplerState public var wrap:Context3DWrapMode ; public var filter:Context3DTextureFilter ; public var mipfilter:Context3DMipFilter ; + public var maxAnisotropy:Float ; + public function new():Void { } diff --git a/openfl/display3D/SamplerState.hx b/openfl/display3D/SamplerState.hx index d440e6b..da40969 100755 --- a/openfl/display3D/SamplerState.hx +++ b/openfl/display3D/SamplerState.hx @@ -5,6 +5,8 @@ class SamplerState public var wrap:Context3DWrapMode ; public var filter:Context3DTextureFilter ; public var mipfilter:Context3DMipFilter ; + public var maxAnisotropy:Float ; + public function new():Void { }