#183 light autobindings for materials

This commit is contained in:
Vadim Lopatin 2016-04-04 16:33:33 +03:00
parent 42464ccd35
commit b00d3265cd
4 changed files with 54 additions and 6 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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) {