mirror of https://github.com/buggins/dlangui.git
#183 light bindings
This commit is contained in:
parent
846c25c652
commit
97cf194319
|
@ -48,10 +48,23 @@ class Light : RefCountedObject {
|
|||
@property void range(float v) { assert(false); }
|
||||
@property float rangeInverse() const { return 1.0; }
|
||||
|
||||
@property float innerAngle() const { assert(false); }
|
||||
@property float innerAngleCos() const { assert(false); }
|
||||
@property float outerAngle() const { assert(false); }
|
||||
@property float outerAngleCos() const { assert(false); }
|
||||
|
||||
/// create new directional light
|
||||
static Light createDirectional(vec3 color) {
|
||||
return new DirectionalLight(color);
|
||||
}
|
||||
/// create new point light
|
||||
static Light createPoint(vec3 color, float range) {
|
||||
return new PointLight(color, range);
|
||||
}
|
||||
/// create new point light
|
||||
static Light createSpot(vec3 color, float range, float innerAngle, float outerAngle) {
|
||||
return new SpotLight(color, range, innerAngle, outerAngle);
|
||||
}
|
||||
}
|
||||
|
||||
protected class DirectionalLight : Light {
|
||||
|
@ -63,7 +76,7 @@ protected class DirectionalLight : Light {
|
|||
protected class PointLight : Light {
|
||||
protected float _range = 1;
|
||||
protected float _rangeInverse = 1;
|
||||
protected this(vec3 color, float range = 1) {
|
||||
protected this(vec3 color, float range) {
|
||||
super(color);
|
||||
_range = range;
|
||||
_rangeInverse = 1 / range;
|
||||
|
@ -79,6 +92,28 @@ protected class PointLight : Light {
|
|||
override @property float rangeInverse() const { return _rangeInverse; }
|
||||
}
|
||||
|
||||
protected class SpotLight : PointLight {
|
||||
protected float _innerAngle;
|
||||
protected float _innerAngleCos;
|
||||
protected float _outerAngle;
|
||||
protected float _outerAngleCos;
|
||||
protected this(vec3 color, float range, float innerAngle, float outerAngle) {
|
||||
import std.math;
|
||||
super(color, range);
|
||||
_innerAngle = innerAngle;
|
||||
_outerAngle = outerAngle;
|
||||
_innerAngleCos = cos(innerAngle);
|
||||
_outerAngleCos = cos(outerAngle);
|
||||
}
|
||||
|
||||
override @property LightType type() const { return LightType.spot; }
|
||||
|
||||
override @property float innerAngle() const { return _innerAngle; }
|
||||
override @property float innerAngleCos() const { return _innerAngleCos; }
|
||||
override @property float outerAngle() const { return _outerAngle; }
|
||||
override @property float outerAngleCos() const { return _outerAngleCos; }
|
||||
}
|
||||
|
||||
alias LightCounts = int[3];
|
||||
|
||||
/// light collection
|
||||
|
@ -87,11 +122,11 @@ struct Lights {
|
|||
Light[] point;
|
||||
Light[] spot;
|
||||
void reset() {
|
||||
directional = null;
|
||||
point = null;
|
||||
spot = null;
|
||||
directional.length = 0;
|
||||
point.length = 0;
|
||||
spot.length = 0;
|
||||
}
|
||||
@property bool empty() { 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; }
|
||||
|
@ -191,6 +226,58 @@ struct Lights {
|
|||
struct LightParams {
|
||||
Lights _lights;
|
||||
|
||||
@property bool empty() const { return _lights.empty; }
|
||||
|
||||
void reset() {
|
||||
_lights.reset();
|
||||
u_directionalLightDirection.length = 0;
|
||||
u_directionalLightColor.length = 0;
|
||||
|
||||
u_pointLightPosition.length = 0;
|
||||
u_pointLightColor.length = 0;
|
||||
u_pointLightRangeInverse.length = 0;
|
||||
|
||||
u_spotLightPosition.length = 0;
|
||||
u_spotLightDirection.length = 0;
|
||||
u_spotLightColor.length = 0;
|
||||
u_spotLightRangeInverse.length = 0;
|
||||
u_spotLightInnerAngleCos.length = 0;
|
||||
u_spotLightOuterAngleCos.length = 0;
|
||||
}
|
||||
|
||||
void reset(ref LightParams params) {
|
||||
reset();
|
||||
if (params._lights.directional.length)
|
||||
_lights.directional ~= params._lights.directional;
|
||||
if (params._lights.point.length)
|
||||
_lights.point ~= params._lights.point;
|
||||
if (params._lights.spot.length)
|
||||
_lights.spot ~= params._lights.spot;
|
||||
|
||||
u_directionalLightDirection ~= params.u_directionalLightDirection;
|
||||
u_directionalLightColor ~= params.u_directionalLightColor;
|
||||
|
||||
u_pointLightPosition ~= params.u_pointLightPosition;
|
||||
u_pointLightColor ~= params.u_pointLightColor;
|
||||
u_pointLightRangeInverse ~= params.u_pointLightRangeInverse;
|
||||
|
||||
u_spotLightPosition ~= params.u_spotLightPosition;
|
||||
u_spotLightDirection ~= params.u_spotLightDirection;
|
||||
u_spotLightColor ~= params.u_spotLightColor;
|
||||
u_spotLightRangeInverse ~= params.u_spotLightRangeInverse;
|
||||
u_spotLightInnerAngleCos ~= params.u_spotLightInnerAngleCos;
|
||||
u_spotLightOuterAngleCos ~= params.u_spotLightOuterAngleCos;
|
||||
}
|
||||
|
||||
void add(ref Lights lights) {
|
||||
foreach(light; lights.directional)
|
||||
add(light);
|
||||
foreach(light; lights.point)
|
||||
add(light);
|
||||
foreach(light; lights.spot)
|
||||
add(light);
|
||||
}
|
||||
|
||||
/// returns true if light is added (not a duplicate, and enabled)
|
||||
bool add(Light light) {
|
||||
if (!light.node || !light.enabled || !_lights.add(light))
|
||||
|
@ -206,7 +293,12 @@ struct LightParams {
|
|||
u_pointLightRangeInverse ~= light.rangeInverse;
|
||||
return true;
|
||||
case LightType.spot:
|
||||
// TODO
|
||||
u_spotLightPosition ~= light.position;
|
||||
u_spotLightDirection ~= light.direction;
|
||||
u_spotLightColor ~= light.color;
|
||||
u_spotLightRangeInverse ~= light.rangeInverse;
|
||||
u_spotLightInnerAngleCos ~= light.innerAngleCos;
|
||||
u_spotLightOuterAngleCos ~= light.outerAngleCos;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -87,7 +87,7 @@ class Material : RefCountedObject {
|
|||
return this;
|
||||
}
|
||||
|
||||
void bind(Node3d node) {
|
||||
void bind(Node3d node, LightParams * lights = null) {
|
||||
assert(!effect.isNull);
|
||||
effect.bind();
|
||||
if (!texture.isNull) {
|
||||
|
@ -109,6 +109,36 @@ class Material : RefCountedObject {
|
|||
_effect.setUniform(DefaultUniform.u_modulateColor, _modulateColor);
|
||||
if (_effect.hasUniform(DefaultUniform.u_modulateAlpha))
|
||||
_effect.setUniform(DefaultUniform.u_modulateAlpha, _modulateAlpha);
|
||||
if (lights && !lights.empty) {
|
||||
if (lights.u_directionalLightDirection.length) {
|
||||
if (_effect.hasUniform(DefaultUniform.u_directionalLightDirection))
|
||||
_effect.setUniform(DefaultUniform.u_directionalLightDirection, lights.u_directionalLightDirection);
|
||||
if (_effect.hasUniform(DefaultUniform.u_directionalLightColor))
|
||||
_effect.setUniform(DefaultUniform.u_directionalLightColor, lights.u_directionalLightColor);
|
||||
}
|
||||
if (lights.u_pointLightPosition.length) {
|
||||
if (_effect.hasUniform(DefaultUniform.u_pointLightPosition))
|
||||
_effect.setUniform(DefaultUniform.u_pointLightPosition, lights.u_pointLightPosition);
|
||||
if (_effect.hasUniform(DefaultUniform.u_pointLightColor))
|
||||
_effect.setUniform(DefaultUniform.u_pointLightColor, lights.u_pointLightColor);
|
||||
if (_effect.hasUniform(DefaultUniform.u_pointLightRangeInverse))
|
||||
_effect.setUniform(DefaultUniform.u_pointLightRangeInverse, lights.u_pointLightRangeInverse);
|
||||
}
|
||||
if (lights.u_spotLightPosition.length) {
|
||||
if (_effect.hasUniform(DefaultUniform.u_spotLightPosition))
|
||||
_effect.setUniform(DefaultUniform.u_spotLightPosition, lights.u_spotLightPosition);
|
||||
if (_effect.hasUniform(DefaultUniform.u_spotLightDirection))
|
||||
_effect.setUniform(DefaultUniform.u_spotLightDirection, lights.u_spotLightDirection);
|
||||
if (_effect.hasUniform(DefaultUniform.u_spotLightColor))
|
||||
_effect.setUniform(DefaultUniform.u_spotLightColor, lights.u_spotLightColor);
|
||||
if (_effect.hasUniform(DefaultUniform.u_spotLightRangeInverse))
|
||||
_effect.setUniform(DefaultUniform.u_spotLightRangeInverse, lights.u_spotLightRangeInverse);
|
||||
if (_effect.hasUniform(DefaultUniform.u_spotLightInnerAngleCos))
|
||||
_effect.setUniform(DefaultUniform.u_spotLightInnerAngleCos, lights.u_spotLightInnerAngleCos);
|
||||
if (_effect.hasUniform(DefaultUniform.u_spotLightOuterAngleCos))
|
||||
_effect.setUniform(DefaultUniform.u_spotLightOuterAngleCos, lights.u_spotLightOuterAngleCos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawMesh(Mesh mesh) {
|
||||
|
|
|
@ -35,9 +35,28 @@ class Model : DrawableObject {
|
|||
return this;
|
||||
}
|
||||
|
||||
protected static __gshared LightParams _lightParamsBuffer;
|
||||
@property protected LightParams * lights(Node3d node) {
|
||||
if (!node.scene)
|
||||
return null;
|
||||
if (_lights.empty) {
|
||||
if (node.scene.boundLights.empty)
|
||||
return null;
|
||||
return node.scene.boundLightsPtr;
|
||||
}
|
||||
if (node.scene.boundLights.empty) {
|
||||
_lightParamsBuffer.reset();
|
||||
_lightParamsBuffer.add(_lights);
|
||||
} else {
|
||||
_lightParamsBuffer.reset(node.scene.boundLights);
|
||||
_lightParamsBuffer.add(_lights);
|
||||
}
|
||||
return &_lightParamsBuffer;
|
||||
}
|
||||
|
||||
override void draw(Node3d node, bool wireframe) {
|
||||
/// override it
|
||||
_material.bind(node);
|
||||
_material.bind(node, lights(node));
|
||||
_material.drawMesh(_mesh);
|
||||
_material.unbind();
|
||||
}
|
||||
|
|
|
@ -69,11 +69,15 @@ class Scene3d : Node3d {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected Lights _lights;
|
||||
protected LightParams _lights;
|
||||
|
||||
@property ref const(Lights) boundLights() {
|
||||
@property ref LightParams boundLights() {
|
||||
return _lights;
|
||||
}
|
||||
|
||||
@property LightParams * boundLightsPtr() {
|
||||
return _lights.empty ? null : &_lights;
|
||||
}
|
||||
}
|
||||
|
||||
/// depth-first recursive node traversion, stops if visitor returns true
|
||||
|
|
Loading…
Reference in New Issue