mirror of https://github.com/buggins/dlangui.git
#183 light bindings
This commit is contained in:
parent
5f0356b3d9
commit
846c25c652
|
@ -1595,6 +1595,17 @@ struct mat4 {
|
|||
return (a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0);
|
||||
}
|
||||
|
||||
@property vec3 forwardVector() const
|
||||
{
|
||||
return vec3(-m[8], -m[9], -m[10]);
|
||||
}
|
||||
|
||||
@property vec3 backVector() const
|
||||
{
|
||||
return vec3(m[8], m[9], m[10]);
|
||||
}
|
||||
|
||||
|
||||
static __gshared const mat4 IDENTITY;
|
||||
}
|
||||
|
||||
|
|
|
@ -319,6 +319,14 @@ class GLProgram : dlangui.graphics.scene.mesh.GraphicsEffect {
|
|||
return res;
|
||||
}
|
||||
|
||||
override void setUniform(string uniformName, const vec2[] vec) {
|
||||
checkgl!glUniform2fv(getUniformLocation(uniformName), cast(int)vec.length, vec[0].vec.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(DefaultUniform id, const vec2[] vec) {
|
||||
checkgl!glUniform2fv(getUniformLocation(id), cast(int)vec.length, vec[0].vec.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(string uniformName, vec2 vec) {
|
||||
checkgl!glUniform2fv(getUniformLocation(uniformName), 1, vec.vec.ptr);
|
||||
}
|
||||
|
@ -335,6 +343,14 @@ class GLProgram : dlangui.graphics.scene.mesh.GraphicsEffect {
|
|||
checkgl!glUniform3fv(getUniformLocation(id), 1, vec.vec.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(string uniformName, const vec3[] vec) {
|
||||
checkgl!glUniform3fv(getUniformLocation(uniformName), cast(int)vec.length, vec[0].vec.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(DefaultUniform id, const vec3[] vec) {
|
||||
checkgl!glUniform3fv(getUniformLocation(id), cast(int)vec.length, vec[0].vec.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(string uniformName, vec4 vec) {
|
||||
checkgl!glUniform4fv(getUniformLocation(uniformName), 1, vec.vec.ptr);
|
||||
}
|
||||
|
@ -343,6 +359,14 @@ class GLProgram : dlangui.graphics.scene.mesh.GraphicsEffect {
|
|||
checkgl!glUniform4fv(getUniformLocation(id), 1, vec.vec.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(string uniformName, const vec4[] vec) {
|
||||
checkgl!glUniform4fv(getUniformLocation(uniformName), cast(int)vec.length, vec[0].vec.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(DefaultUniform id, const vec4[] vec) {
|
||||
checkgl!glUniform4fv(getUniformLocation(id), cast(int)vec.length, vec[0].vec.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(string uniformName, ref const(mat4) matrix) {
|
||||
checkgl!glUniformMatrix4fv(getUniformLocation(uniformName), 1, false, matrix.m.ptr);
|
||||
}
|
||||
|
@ -351,6 +375,30 @@ class GLProgram : dlangui.graphics.scene.mesh.GraphicsEffect {
|
|||
checkgl!glUniformMatrix4fv(getUniformLocation(id), 1, false, matrix.m.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(string uniformName, const(mat4)[] matrix) {
|
||||
checkgl!glUniformMatrix4fv(getUniformLocation(uniformName), cast(int)matrix.length, false, matrix[0].m.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(DefaultUniform id, const(mat4)[] matrix) {
|
||||
checkgl!glUniformMatrix4fv(getUniformLocation(id), cast(int)matrix.length, false, matrix[0].m.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(string uniformName, float v) {
|
||||
checkgl!glUniform1f(getUniformLocation(uniformName), v);
|
||||
}
|
||||
|
||||
override void setUniform(DefaultUniform id, float v) {
|
||||
checkgl!glUniform1f(getUniformLocation(id), v);
|
||||
}
|
||||
|
||||
override void setUniform(string uniformName, const float[] v) {
|
||||
checkgl!glUniform1fv(getUniformLocation(uniformName), cast(int)v.length, v.ptr);
|
||||
}
|
||||
|
||||
override void setUniform(DefaultUniform id, const float[] v) {
|
||||
checkgl!glUniform1fv(getUniformLocation(id), cast(int)v.length, v.ptr);
|
||||
}
|
||||
|
||||
/// returns true if effect has uniform
|
||||
override bool hasUniform(DefaultUniform id) {
|
||||
return getUniformLocation(id) >= 0;
|
||||
|
|
|
@ -137,6 +137,8 @@ class Effect : GLProgram {
|
|||
return getAttribLocation(DefaultAttribute.a_color);
|
||||
case TEXCOORD0:
|
||||
return getAttribLocation(DefaultAttribute.a_texCoord);
|
||||
case NORMAL:
|
||||
return getAttribLocation(DefaultAttribute.a_normal);
|
||||
default:
|
||||
return super.getVertexElementLocation(type);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ module dlangui.graphics.scene.light;
|
|||
|
||||
import dlangui.core.math3d;
|
||||
import dlangui.core.types;
|
||||
import dlangui.graphics.scene.node;
|
||||
|
||||
import std.conv : to;
|
||||
|
||||
enum LightType : ubyte {
|
||||
directional,
|
||||
|
@ -12,12 +15,39 @@ enum LightType : ubyte {
|
|||
/// Reference counted Light object
|
||||
alias LightRef = Ref!Light;
|
||||
|
||||
class Light : RefCountedObject {
|
||||
class Light : RefCountedObject {
|
||||
|
||||
protected Node3d _node;
|
||||
|
||||
protected vec3 _color;
|
||||
protected this(vec3 color) {}
|
||||
@property vec3 color() { return _color; }
|
||||
|
||||
protected bool _autobind = true;
|
||||
protected bool _enabled = true;
|
||||
|
||||
protected this(vec3 color) { _color = color; }
|
||||
|
||||
@property vec3 color() const { return _color; }
|
||||
@property Light color(vec3 c) { _color = c; return this; }
|
||||
@property LightType type() { return LightType.directional; }
|
||||
@property LightType type() const { return LightType.directional; }
|
||||
|
||||
@property bool autobind() const { return _autobind; }
|
||||
@property Light autobind(bool flg) { _autobind = flg; return this; }
|
||||
|
||||
@property bool enabled() const { return _enabled; }
|
||||
@property Light enabled(bool flg) { _enabled = flg; return this; }
|
||||
|
||||
@property Node3d node() { return _node; }
|
||||
@property Light node(Node3d n) { _node = n; return this; }
|
||||
|
||||
/// direction in world coordinates
|
||||
@property vec3 direction() { return _node ? _node.forwardVectorWorld : vec3(0, 0, 1); }
|
||||
/// position in world coordinates
|
||||
@property vec3 position() { return _node ? _node.translationWorld : vec3(0, 0, 0); }
|
||||
|
||||
@property float range() const { return 1.0; }
|
||||
@property void range(float v) { assert(false); }
|
||||
@property float rangeInverse() const { return 1.0; }
|
||||
|
||||
/// create new directional light
|
||||
static Light createDirectional(vec3 color) {
|
||||
return new DirectionalLight(color);
|
||||
|
@ -29,3 +59,171 @@ protected class DirectionalLight : Light {
|
|||
super(color);
|
||||
}
|
||||
}
|
||||
|
||||
protected class PointLight : Light {
|
||||
protected float _range = 1;
|
||||
protected float _rangeInverse = 1;
|
||||
protected this(vec3 color, float range = 1) {
|
||||
super(color);
|
||||
_range = range;
|
||||
_rangeInverse = 1 / range;
|
||||
}
|
||||
|
||||
override @property LightType type() const { return LightType.point; }
|
||||
|
||||
override @property float range() const { return _range; }
|
||||
override @property void range(float v) {
|
||||
_range = v;
|
||||
_rangeInverse = 1 / v;
|
||||
}
|
||||
override @property float rangeInverse() const { return _rangeInverse; }
|
||||
}
|
||||
|
||||
alias LightCounts = int[3];
|
||||
|
||||
/// light collection
|
||||
struct Lights {
|
||||
Light[] directional;
|
||||
Light[] point;
|
||||
Light[] spot;
|
||||
void reset() {
|
||||
directional = null;
|
||||
point = null;
|
||||
spot = null;
|
||||
}
|
||||
@property bool empty() { 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; }
|
||||
@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;
|
||||
char[] buf;
|
||||
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 cast(string)buf;
|
||||
}
|
||||
void remove(Light light) {
|
||||
import std.algorithm : remove;
|
||||
switch(light.type) {
|
||||
case LightType.directional:
|
||||
foreach(index, v; directional)
|
||||
if (v is light) {
|
||||
directional = directional.remove(index);
|
||||
return;
|
||||
}
|
||||
directional ~= light;
|
||||
break;
|
||||
case LightType.point:
|
||||
foreach(index, v; point)
|
||||
if (v is light) {
|
||||
point = point.remove(index);
|
||||
return;
|
||||
}
|
||||
point ~= light;
|
||||
break;
|
||||
case LightType.spot:
|
||||
foreach(index, v; spot)
|
||||
if (v is light) {
|
||||
spot = spot.remove(index);
|
||||
return;
|
||||
}
|
||||
spot ~= light;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/// returns true if light is added (not a duplicate, and enabled)
|
||||
bool add(Light light) {
|
||||
switch(light.type) {
|
||||
case LightType.directional:
|
||||
foreach(v; directional)
|
||||
if (v is light)
|
||||
return false;
|
||||
directional ~= light;
|
||||
return true;
|
||||
case LightType.point:
|
||||
foreach(v; point)
|
||||
if (v is light)
|
||||
return false;
|
||||
point ~= light;
|
||||
return true;
|
||||
case LightType.spot:
|
||||
foreach(v; spot)
|
||||
if (v is light)
|
||||
return false;
|
||||
spot ~= light;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Lights clone() {
|
||||
Lights res;
|
||||
if (directional.length)
|
||||
res.directional ~= directional;
|
||||
if (point.length)
|
||||
res.point ~= point;
|
||||
if (spot.length)
|
||||
res.spot ~= spot;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
struct LightParams {
|
||||
Lights _lights;
|
||||
|
||||
/// returns true if light is added (not a duplicate, and enabled)
|
||||
bool add(Light light) {
|
||||
if (!light.node || !light.enabled || !_lights.add(light))
|
||||
return false;
|
||||
switch(light.type) {
|
||||
case LightType.directional:
|
||||
u_directionalLightDirection ~= light.direction;
|
||||
u_directionalLightColor ~= light.color;
|
||||
return true;
|
||||
case LightType.point:
|
||||
u_pointLightPosition ~= light.position;
|
||||
u_pointLightColor ~= light.color;
|
||||
u_pointLightRangeInverse ~= light.rangeInverse;
|
||||
return true;
|
||||
case LightType.spot:
|
||||
// TODO
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
vec3[] u_directionalLightDirection;
|
||||
vec3[] u_directionalLightColor;
|
||||
|
||||
vec3[] u_pointLightPosition;
|
||||
vec3[] u_pointLightColor;
|
||||
float[] u_pointLightRangeInverse;
|
||||
|
||||
vec3[] u_spotLightPosition;
|
||||
vec3[] u_spotLightDirection;
|
||||
vec3[] u_spotLightColor;
|
||||
float[] u_spotLightRangeInverse;
|
||||
float[] u_spotLightInnerAngleCos;
|
||||
float[] u_spotLightOuterAngleCos;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import dlangui.graphics.gldrawbuf;
|
|||
import dlangui.graphics.scene.effect;
|
||||
import dlangui.graphics.scene.node;
|
||||
import dlangui.graphics.scene.mesh;
|
||||
import dlangui.graphics.scene.light;
|
||||
|
||||
/// Reference counted Material object
|
||||
alias MaterialRef = Ref!Material;
|
||||
|
@ -25,6 +26,8 @@ class Material : RefCountedObject {
|
|||
// colors
|
||||
protected vec4 _diffuseColor = vec4(1, 1, 1, 1);
|
||||
protected vec3 _ambientColor = vec3(1, 1, 1);
|
||||
protected vec4 _modulateColor = vec4(1, 1, 1, 1);
|
||||
protected float _modulateAlpha = 1;
|
||||
|
||||
// TODO: more material properties
|
||||
|
||||
|
@ -40,6 +43,10 @@ class Material : RefCountedObject {
|
|||
@property Material diffuseColor(vec4 color) { _diffuseColor = color; return this; }
|
||||
@property vec3 ambientColor() { return _ambientColor; }
|
||||
@property Material ambientColor(vec3 color) { _ambientColor = color; return this; }
|
||||
@property vec4 modulateColor() { return _modulateColor; }
|
||||
@property Material modulateColor(vec4 color) { _modulateColor = color; return this; }
|
||||
@property float modulateAlpha() { return _modulateAlpha; }
|
||||
@property Material modulateColor(float a) { _modulateAlpha = a; return this; }
|
||||
|
||||
@property EffectRef effect() {
|
||||
if (_effect.isNull && !_effectId.empty)
|
||||
|
@ -98,6 +105,10 @@ class Material : RefCountedObject {
|
|||
_effect.setUniform(DefaultUniform.u_ambientColor, _ambientColor);
|
||||
if (_effect.hasUniform(DefaultUniform.u_diffuseColor))
|
||||
_effect.setUniform(DefaultUniform.u_diffuseColor, _diffuseColor);
|
||||
if (_effect.hasUniform(DefaultUniform.u_modulateColor))
|
||||
_effect.setUniform(DefaultUniform.u_modulateColor, _modulateColor);
|
||||
if (_effect.hasUniform(DefaultUniform.u_modulateAlpha))
|
||||
_effect.setUniform(DefaultUniform.u_modulateAlpha, _modulateAlpha);
|
||||
}
|
||||
|
||||
void drawMesh(Mesh mesh) {
|
||||
|
|
|
@ -15,20 +15,44 @@ abstract class GraphicsEffect : RefCountedObject {
|
|||
|
||||
void setUniform(string uniformName, ref const(mat4) matrix);
|
||||
|
||||
void setUniform(string uniformName, const(mat4)[] matrix);
|
||||
|
||||
void setUniform(string uniformName, float v);
|
||||
|
||||
void setUniform(string uniformName, const float v[]);
|
||||
|
||||
void setUniform(string uniformName, vec2 vec);
|
||||
|
||||
void setUniform(string uniformName, const vec2[] vec);
|
||||
|
||||
void setUniform(string uniformName, vec3 vec);
|
||||
|
||||
void setUniform(string uniformName, const vec3[] vec);
|
||||
|
||||
void setUniform(string uniformName, vec4 vec);
|
||||
|
||||
void setUniform(string uniformName, const vec4[] vec);
|
||||
|
||||
void setUniform(DefaultUniform id, ref const(mat4) matrix);
|
||||
|
||||
void setUniform(DefaultUniform id, const(mat4)[] matrix);
|
||||
|
||||
void setUniform(DefaultUniform id, float v);
|
||||
|
||||
void setUniform(DefaultUniform id, const float[] v);
|
||||
|
||||
void setUniform(DefaultUniform id, vec2 vec);
|
||||
|
||||
void setUniform(DefaultUniform id, const vec2[] vec);
|
||||
|
||||
void setUniform(DefaultUniform id, vec3 vec);
|
||||
|
||||
void setUniform(DefaultUniform id, const vec3[] vec);
|
||||
|
||||
void setUniform(DefaultUniform id, vec4 vec);
|
||||
|
||||
void setUniform(DefaultUniform id, const vec4[] vec);
|
||||
|
||||
/// returns true if effect has uniform
|
||||
bool hasUniform(DefaultUniform id);
|
||||
|
||||
|
@ -42,7 +66,13 @@ enum DefaultUniform : int {
|
|||
// colors
|
||||
u_ambientColor, // vec3
|
||||
u_diffuseColor, // vec4
|
||||
u_lightmapTexture, // sampler2D
|
||||
|
||||
// textures
|
||||
u_diffuseTexture, //uniform sampler2D u_diffuseTexture;
|
||||
u_lightmapTexture, //uniform sampler2D u_lightmapTexture;
|
||||
u_normalmapTexture, //uniform sampler2D u_normalmapTexture;
|
||||
|
||||
// lights
|
||||
u_directionalLightColor, //uniform vec3 u_directionalLightColor[DIRECTIONAL_LIGHT_COUNT];
|
||||
u_directionalLightDirection, //uniform vec3 u_directionalLightDirection[DIRECTIONAL_LIGHT_COUNT];
|
||||
u_pointLightColor, //uniform vec3 u_pointLightColor[POINT_LIGHT_COUNT];
|
||||
|
@ -52,7 +82,9 @@ enum DefaultUniform : int {
|
|||
u_spotLightRangeInverse, //uniform float u_spotLightRangeInverse[SPOT_LIGHT_COUNT];
|
||||
u_spotLightInnerAngleCos, //uniform float u_spotLightInnerAngleCos[SPOT_LIGHT_COUNT];
|
||||
u_spotLightOuterAngleCos, //uniform float u_spotLightOuterAngleCos[SPOT_LIGHT_COUNT];
|
||||
u_spotLightPosition, //uniform vec3 u_spotLightPosition[SPOT_LIGHT_COUNT];
|
||||
u_spotLightDirection, //uniform vec3 u_spotLightDirection[SPOT_LIGHT_COUNT];
|
||||
|
||||
u_specularExponent, //uniform float u_specularExponent;
|
||||
u_modulateColor, //uniform vec4 u_modulateColor;
|
||||
u_modulateAlpha, //uniform float u_modulateAlpha;
|
||||
|
@ -60,10 +92,11 @@ enum DefaultUniform : int {
|
|||
// matrix
|
||||
u_worldViewProjectionMatrix, //uniform mat4 u_worldViewProjectionMatrix;
|
||||
u_inverseTransposeWorldViewMatrix, //uniform mat4 u_inverseTransposeWorldViewMatrix;
|
||||
u_worldViewMatrix, //uniform mat4 u_worldViewMatrix;
|
||||
u_matrixPalette, //uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
|
||||
u_cameraPosition, //uniform vec3 u_cameraPosition;
|
||||
u_worldMatrix, //uniform mat4 u_worldMatrix;
|
||||
u_worldViewMatrix, //uniform mat4 u_worldViewMatrix;
|
||||
u_cameraPosition, //uniform vec3 u_cameraPosition;
|
||||
|
||||
u_matrixPalette, //uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
|
||||
u_clipPlane, //uniform vec4 u_clipPlane;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,13 @@ module dlangui.graphics.scene.model;
|
|||
import dlangui.graphics.scene.drawableobject;
|
||||
import dlangui.graphics.scene.mesh;
|
||||
import dlangui.graphics.scene.material;
|
||||
import dlangui.graphics.scene.light;
|
||||
|
||||
class Model : DrawableObject {
|
||||
protected MaterialRef _material;
|
||||
protected MeshRef _mesh;
|
||||
protected bool _autobindLights = true;
|
||||
protected Lights _lights;
|
||||
|
||||
this() {
|
||||
}
|
||||
|
@ -19,6 +22,19 @@ class Model : DrawableObject {
|
|||
@property ref MaterialRef material() { return _material; }
|
||||
@property ref MeshRef mesh() { return _mesh; }
|
||||
|
||||
@property bool autobindLights() { return _autobindLights; }
|
||||
@property Model autobindLights(bool flg) { _autobindLights = flg; return this; }
|
||||
|
||||
Model bindLight(Light light) {
|
||||
_lights.add(light);
|
||||
return this;
|
||||
}
|
||||
|
||||
Model unbindLight(Light light) {
|
||||
_lights.remove(light);
|
||||
return this;
|
||||
}
|
||||
|
||||
override void draw(Node3d node, bool wireframe) {
|
||||
/// override it
|
||||
_material.bind(node);
|
||||
|
|
|
@ -42,6 +42,18 @@ class Node3d : Transform {
|
|||
/// light attached to node
|
||||
@property ref LightRef light() { return _light; }
|
||||
|
||||
/// attach light to node
|
||||
@property Node3d light(Light v) {
|
||||
if (_light.get is v)
|
||||
return this;
|
||||
Node3d oldNode = v.node;
|
||||
v.node = this;
|
||||
_light = v;
|
||||
if (oldNode)
|
||||
oldNode._light = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// returns scene for node
|
||||
@property Scene3d scene() {
|
||||
if (_scene)
|
||||
|
@ -162,4 +174,13 @@ class Node3d : Transform {
|
|||
worldMatrix.getTranslation(translation);
|
||||
return translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the forward vector of the Node in world space.
|
||||
*
|
||||
* @return The forward vector in world space.
|
||||
*/
|
||||
@property vec3 forwardVectorWorld() {
|
||||
return worldMatrix.forwardVector;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,10 +166,10 @@ struct ObjModelImport {
|
|||
if (!mesh.isNull)
|
||||
return;
|
||||
if (_txCount) {
|
||||
mesh = new Mesh(VertexFormat(VertexElementType.POSITION, VertexElementType.NORMAL, VertexElementType.COLOR, VertexElementType.TEXCOORD0));
|
||||
mesh = new Mesh(VertexFormat(VertexElementType.POSITION, VertexElementType.NORMAL, /*VertexElementType.COLOR, */ VertexElementType.TEXCOORD0));
|
||||
_meshHasTexture = true;
|
||||
} else {
|
||||
mesh = new Mesh(VertexFormat(VertexElementType.POSITION, VertexElementType.NORMAL, VertexElementType.COLOR));
|
||||
mesh = new Mesh(VertexFormat(VertexElementType.POSITION, VertexElementType.NORMAL /*, VertexElementType.COLOR*/));
|
||||
_meshHasTexture = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ module dlangui.graphics.scene.scene3d;
|
|||
import dlangui.core.types;
|
||||
import dlangui.graphics.scene.node;
|
||||
import dlangui.graphics.scene.camera;
|
||||
import dlangui.graphics.scene.light;
|
||||
|
||||
public import dlangui.core.math3d;
|
||||
|
||||
|
@ -47,6 +48,7 @@ class Scene3d : Node3d {
|
|||
protected bool _wireframe;
|
||||
void drawScene(bool wireframe) {
|
||||
_wireframe = wireframe;
|
||||
updateAutoboundLights();
|
||||
visit(this, &sceneDrawVisitor);
|
||||
}
|
||||
|
||||
|
@ -55,6 +57,23 @@ class Scene3d : Node3d {
|
|||
node.drawable.draw(node, _wireframe);
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateAutoboundLights() {
|
||||
_lights.reset();
|
||||
visit(this, &lightBindingVisitor);
|
||||
}
|
||||
|
||||
protected bool lightBindingVisitor(Node3d node) {
|
||||
if (!node.light.isNull && node.light.enabled && node.light.autobind)
|
||||
_lights.add(node.light);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Lights _lights;
|
||||
|
||||
@property ref const(Lights) boundLights() {
|
||||
return _lights;
|
||||
}
|
||||
}
|
||||
|
||||
/// depth-first recursive node traversion, stops if visitor returns true
|
||||
|
|
Loading…
Reference in New Issue