diff --git a/examples/d3d/src/d3d.d b/examples/d3d/src/d3d.d index 0969f8b7..a7392712 100644 --- a/examples/d3d/src/d3d.d +++ b/examples/d3d/src/d3d.d @@ -9,6 +9,7 @@ import dlangui.graphics.scene.effect; import dlangui.graphics.scene.model; import dlangui.graphics.scene.node; import dlangui.graphics.scene.objimport; +import dlangui.graphics.scene.light; import dlangui.graphics.glsupport; import dlangui.graphics.gldrawbuf; import derelict.opengl3.gl3; @@ -113,6 +114,12 @@ class UiWidget : VerticalLayout, CellVisitor { _scene.activeCamera = _cam; + Node3d dirLightNode = new Node3d(); + dirLightNode.rotateY(-15); + dirLightNode.rotateX(20); + dirLightNode.light = Light.createDirectional(vec3(1, 0.5, 0.5)); + _scene.addChild(dirLightNode); + int x0 = 0; int y0 = 0; int z0 = 0; diff --git a/src/dlangui/graphics/scene/effect.d b/src/dlangui/graphics/scene/effect.d index c0c0b859..f6800100 100644 --- a/src/dlangui/graphics/scene/effect.d +++ b/src/dlangui/graphics/scene/effect.d @@ -160,8 +160,10 @@ class EffectCache { } static private void onObjectDestroyed(EffectId id) { - if (id in _instance._map) + if (id in _instance._map) { + Log.d("Destroyed effect instance: ", id); _instance._map.remove(id); + } } /// get effect from cache or create new if not exist @@ -175,6 +177,7 @@ class EffectCache { return *p; } Effect e = new Effect(id); + Log.d("New effect instance: ", id); _map[id] = e; return e; } @@ -192,6 +195,21 @@ struct EffectId { definitions = defs; } + this(ref EffectId v, string additionalParams) { + import std.string : empty; + vertexShaderName = v.vertexShaderName; + fragmentShaderName = v.fragmentShaderName; + definitions = v.definitions; + if (!additionalParams.empty) { + if (!definitions.empty) { + definitions ~= ";"; + definitions ~= additionalParams; + } else { + definitions = additionalParams; + } + } + } + /// returns true if ID is not assigned @property bool empty() { return !vertexShaderName.length || !vertexShaderName.length; diff --git a/src/dlangui/graphics/scene/light.d b/src/dlangui/graphics/scene/light.d index 47f2a2f0..e2d540a9 100644 --- a/src/dlangui/graphics/scene/light.d +++ b/src/dlangui/graphics/scene/light.d @@ -126,7 +126,7 @@ struct Lights { point.length = 0; spot.length = 0; } - @property bool empty() const { return directional.length + point.length + spot.length > 0; } + @property bool empty() const { return directional.length + point.length + spot.length == 0; } /// returns point types by type @property LightCounts counts() const { return [cast(int)directional.length, cast(int)point.length, cast(int)spot.length]; } @property int directionalCount() const { return cast(int)directional.length; } @@ -136,7 +136,8 @@ struct Lights { @property string defs() const { if (!directional.length && !point.length && !spot.length) return null; - char[] buf; + static __gshared char[] buf; + buf.length = 0; // reset buffer if (directional.length) { buf ~= "DIRECTIONAL_LIGHT_COUNT "; buf ~= directional.length.to!string; @@ -153,7 +154,7 @@ struct Lights { buf ~= "SPOT_LIGHT_COUNT "; buf ~= spot.length.to!string; } - return cast(string)buf; + return buf.dup; } void remove(Light light) { import std.algorithm : remove; @@ -227,6 +228,7 @@ struct LightParams { Lights _lights; @property bool empty() const { return _lights.empty; } + @property string defs() const { return _lights.defs; } void reset() { _lights.reset(); diff --git a/src/dlangui/graphics/scene/material.d b/src/dlangui/graphics/scene/material.d index 9940617e..ef1ee84f 100644 --- a/src/dlangui/graphics/scene/material.d +++ b/src/dlangui/graphics/scene/material.d @@ -18,6 +18,8 @@ class Material : RefCountedObject { // effect protected EffectRef _effect; protected EffectId _effectId; + protected string _autoEffectParams; + protected EffectId _autoEffectId; // textures protected TextureRef _texture; @@ -36,6 +38,8 @@ class Material : RefCountedObject { this(EffectId effectId, string textureId) { _effectId = effectId; + _autoEffectParams = null; + _autoEffectId = effectId; _textureId = textureId; } @@ -49,8 +53,8 @@ class Material : RefCountedObject { @property Material modulateColor(float a) { _modulateAlpha = a; return this; } @property EffectRef effect() { - if (_effect.isNull && !_effectId.empty) - _effect = EffectCache.instance.get(_effectId); + if (_effect.isNull && !_autoEffectId.empty) + _effect = EffectCache.instance.get(_autoEffectId); return _effect; } /// set as effect instance @@ -63,10 +67,20 @@ class Material : RefCountedObject { if (_effectId == effectId) return this; // no change _effectId = effectId; + _autoEffectId = EffectId(_effectId, _autoEffectParams); _effect.clear(); return this; } + protected @property Material autoEffectParams(string params) { + if (_autoEffectParams != params && !_effectId.empty) { + _autoEffectId = EffectId(_effectId, params); + _autoEffectParams = params; + _effect.clear(); + } + return this; + } + @property TextureRef texture() { if (_texture.isNull && _textureId.length) { _texture = GLTextureCache.instance.get(_textureId); @@ -87,7 +101,14 @@ class Material : RefCountedObject { return this; } + string calcAutoEffectParams(LightParams * lights) { + if (!lights || lights.empty) + return null; + return lights.defs; + } + void bind(Node3d node, LightParams * lights = null) { + autoEffectParams = calcAutoEffectParams(lights); assert(!effect.isNull); effect.bind(); if (!texture.isNull) {