diff --git a/examples/d3d/src/d3d.d b/examples/d3d/src/d3d.d index 732375a1..2b465b84 100644 --- a/examples/d3d/src/d3d.d +++ b/examples/d3d/src/d3d.d @@ -115,10 +115,11 @@ class UiWidget : VerticalLayout, CellVisitor { _scene.activeCamera = _cam; Node3d dirLightNode = new Node3d(); - dirLightNode.lookAt(vec3(-5, -5, -5), vec3(0, 0, 0), vec3(0, 1, 0)); + //dirLightNode.lookAt(vec3(-5, -5, -5), vec3(0, 0, 0), vec3(0, 1, 0)); //dirLightNode.rotateY(-15); //dirLightNode.rotateX(20); - dirLightNode.light = Light.createDirectional(vec3(1, 0.5, 0.5)); + dirLightNode.light = Light.createPoint(vec3(1, 0.5, 0.5), 5); //Light.createDirectional(vec3(1, 0.5, 0.5)); + dirLightNode.light.enabled = false; _scene.addChild(dirLightNode); int x0 = 0; @@ -137,7 +138,7 @@ class UiWidget : VerticalLayout, CellVisitor { _mesh.addCubeMesh(vec3(x0+ i * 2 + 1.0f, y0+-i * 2 + 1.0f, z0+ i * 2 + 1.0f), 0.2f, vec4(i / 12, 1 - i / 12, i / 12, 1)); _mesh.addCubeMesh(vec3(x0+ -i * 2 - 1.0f, y0+-i * 2 - 1.0f, z0+ -i * 2 - 1.0f), 0.2f, vec4(1 - i / 12, i / 12, i / 12, 1)); } - Material cubeMaterial = new Material(EffectId("textured.vert", "textured.frag", null), "crate"); + Material cubeMaterial = new Material(EffectId("textured.vert", "textured.frag", "SPECULAR"), "crate"); Model cubeDrawable = new Model(cubeMaterial, _mesh); Node3d cubeNode = new Node3d("cubes", cubeDrawable); _scene.addChild(cubeNode); @@ -146,8 +147,8 @@ class UiWidget : VerticalLayout, CellVisitor { string src = loadTextResource("suzanne.obj"); importer.parse(src); Log.d("suzanne mesh:", importer.mesh.dumpVertexes(20)); - Material suzanneMaterial = new Material(EffectId("colored.vert", "colored.frag", null), null); //"DIRECTIONAL_LIGHT_COUNT 1" - suzanneMaterial.ambientColor = vec3(0.5, 1.0, 0.5); + Material suzanneMaterial = new Material(EffectId("colored.vert", "colored.frag", "SPECULAR"), null); //"SPECULAR" + suzanneMaterial.ambientColor = vec3(0.0, 0.0, 0.0); suzanneMaterial.diffuseColor = vec4(1.0, 0.7, 0.7, 1.0); Model suzanneDrawable = new Model(suzanneMaterial, importer.mesh); Node3d suzanneNode = new Node3d("suzanne", suzanneDrawable); diff --git a/src/dlangui/graphics/scene/light.d b/src/dlangui/graphics/scene/light.d index e2d540a9..b22ba6f6 100644 --- a/src/dlangui/graphics/scene/light.d +++ b/src/dlangui/graphics/scene/light.d @@ -132,30 +132,30 @@ struct Lights { @property int directionalCount() const { return cast(int)directional.length; } @property int pointCount() const { return cast(int)point.length; } @property int spotCount() const { return cast(int)spot.length; } - /// return light count definition for shaders, e.g. "DIRECTIONAL_LIGHT_COUNT 2;POINT_LIGHT_COUNT 1" - @property string defs() const { - if (!directional.length && !point.length && !spot.length) - return null; - static __gshared char[] buf; - buf.length = 0; // reset buffer - if (directional.length) { - buf ~= "DIRECTIONAL_LIGHT_COUNT "; - buf ~= directional.length.to!string; - } - if (point.length) { - if (buf) - buf ~= ";"; - buf ~= "POINT_LIGHT_COUNT "; - buf ~= point.length.to!string; - } - if (spot.length) { - if (buf) - buf ~= ";"; - buf ~= "SPOT_LIGHT_COUNT "; - buf ~= spot.length.to!string; - } - return buf.dup; - } + ///// return light count definition for shaders, e.g. "DIRECTIONAL_LIGHT_COUNT 2;POINT_LIGHT_COUNT 1" + //@property string defs() const { + // if (!directional.length && !point.length && !spot.length) + // return null; + // static __gshared char[] buf; + // buf.length = 0; // reset buffer + // if (directional.length) { + // buf ~= "DIRECTIONAL_LIGHT_COUNT "; + // buf ~= directional.length.to!string; + // } + // if (point.length) { + // if (buf.length) + // buf ~= ";"; + // buf ~= "POINT_LIGHT_COUNT "; + // buf ~= point.length.to!string; + // } + // if (spot.length) { + // if (buf.length) + // buf ~= ";"; + // buf ~= "SPOT_LIGHT_COUNT "; + // buf ~= spot.length.to!string; + // } + // return buf.dup; + //} void remove(Light light) { import std.algorithm : remove; switch(light.type) { @@ -228,7 +228,7 @@ struct LightParams { Lights _lights; @property bool empty() const { return _lights.empty; } - @property string defs() const { return _lights.defs; } + //@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 ef1ee84f..0bee44dd 100644 --- a/src/dlangui/graphics/scene/material.d +++ b/src/dlangui/graphics/scene/material.d @@ -27,7 +27,7 @@ class Material : RefCountedObject { // colors protected vec4 _diffuseColor = vec4(1, 1, 1, 1); - protected vec3 _ambientColor = vec3(1, 1, 1); + protected vec3 _ambientColor = vec3(0, 0, 0); protected vec4 _modulateColor = vec4(1, 1, 1, 1); protected float _modulateAlpha = 1; @@ -101,14 +101,19 @@ class Material : RefCountedObject { return this; } - string calcAutoEffectParams(LightParams * lights) { - if (!lights || lights.empty) - return null; - return lights.defs; + private AutoParams _lastParams; + private string _lastDefs; + string calcAutoEffectParams(Mesh mesh, LightParams * lights) { + AutoParams newParams = AutoParams(mesh, lights, false); + if (newParams != _lastParams) { + _lastParams = newParams; + _lastDefs = _lastParams.defs; + } + return _lastDefs; } - void bind(Node3d node, LightParams * lights = null) { - autoEffectParams = calcAutoEffectParams(lights); + void bind(Node3d node, Mesh mesh, LightParams * lights = null) { + autoEffectParams = calcAutoEffectParams(mesh, lights); assert(!effect.isNull); effect.bind(); if (!texture.isNull) { @@ -173,3 +178,51 @@ class Material : RefCountedObject { effect.unbind(); } } + +struct AutoParams { + ubyte directionalLightCount = 0; + ubyte pointLightCount = 0; + ubyte spotLightCount = 0; + bool vertexColor = false; + bool specular = false; + this(Mesh mesh, LightParams * lights, bool specular) { + if (mesh) + vertexColor = mesh.hasElement(VertexElementType.COLOR); + if (lights) { + directionalLightCount = cast(ubyte)lights.u_directionalLightDirection.length; + pointLightCount = cast(ubyte)lights.u_pointLightPosition.length; + spotLightCount = cast(ubyte)lights.u_spotLightPosition.length; + } + this.specular = specular; + } + string defs() { + char buf[]; + if (directionalLightCount) { + buf ~= "DIRECTIONAL_LIGHT_COUNT "; + buf ~= directionalLightCount.to!string; + } + if (pointLightCount) { + if (buf.length) + buf ~= ";"; + buf ~= "POINT_LIGHT_COUNT "; + buf ~= pointLightCount.to!string; + } + if (spotLightCount) { + if (buf.length) + buf ~= ";"; + buf ~= "SPOT_LIGHT_COUNT "; + buf ~= spotLightCount.to!string; + } + if (vertexColor) { + if (buf.length) + buf ~= ";"; + buf ~= "VERTEX_COLOR"; + } + if (specular) { + if (buf.length) + buf ~= ";"; + buf ~= "SPECULAR"; + } + return buf.dup; + } +} diff --git a/src/dlangui/graphics/scene/mesh.d b/src/dlangui/graphics/scene/mesh.d index ddb8e238..5412f51e 100644 --- a/src/dlangui/graphics/scene/mesh.d +++ b/src/dlangui/graphics/scene/mesh.d @@ -314,6 +314,11 @@ class Mesh : RefCountedObject { @property ref VertexFormat vertexFormat() { return _vertexFormat; } @property const(VertexFormat) * vertexFormatPtr() { return &_vertexFormat; } + /// returns true if vertex format contains specified element + bool hasElement(VertexElementType type) const { + return _vertexFormat.hasElement(type); + } + //@property ref VertexFormat vertexFormat() { return _vertexFormat; } @property void vertexFormat(VertexFormat format) { diff --git a/src/dlangui/graphics/scene/model.d b/src/dlangui/graphics/scene/model.d index c3d472c8..5c081c38 100644 --- a/src/dlangui/graphics/scene/model.d +++ b/src/dlangui/graphics/scene/model.d @@ -56,7 +56,7 @@ class Model : DrawableObject { override void draw(Node3d node, bool wireframe) { /// override it - _material.bind(node, lights(node)); + _material.bind(node, _mesh, lights(node)); _material.drawMesh(_mesh); _material.unbind(); }