#183 light bindings

This commit is contained in:
Vadim Lopatin 2016-04-04 15:36:16 +03:00
parent 846c25c652
commit 97cf194319
4 changed files with 155 additions and 10 deletions

View File

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

View File

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

View File

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

View File

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