mirror of
https://github.com/bloeys/nmage.git
synced 2025-12-29 13:28:20 +00:00
Much nicer point light formulas
This commit is contained in:
108
main.go
108
main.go
@ -82,18 +82,14 @@ func (d *DirLight) GetProjViewMat() gglm.Mat4 {
|
|||||||
return *projMat.Mul(&viewMat)
|
return *projMat.Mul(&viewMat)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check https://wiki.ogre3d.org/tiki-index.php?page=-Point+Light+Attenuation for values
|
// Based on: https://lisyarus.github.io/blog/posts/point-light-attenuation.html
|
||||||
type PointLight struct {
|
type PointLight struct {
|
||||||
Pos gglm.Vec3
|
Pos gglm.Vec3
|
||||||
DiffuseColor gglm.Vec3
|
DiffuseColor gglm.Vec3
|
||||||
SpecularColor gglm.Vec3
|
SpecularColor gglm.Vec3
|
||||||
|
|
||||||
// @TODO
|
|
||||||
Radius float32
|
Radius float32
|
||||||
|
Falloff float32
|
||||||
Constant float32
|
|
||||||
Linear float32
|
|
||||||
Quadratic float32
|
|
||||||
|
|
||||||
FarPlane float32
|
FarPlane float32
|
||||||
}
|
}
|
||||||
@ -278,38 +274,32 @@ var (
|
|||||||
Pos: gglm.NewVec3(0, 2, -2),
|
Pos: gglm.NewVec3(0, 2, -2),
|
||||||
DiffuseColor: gglm.NewVec3(1, 0, 0),
|
DiffuseColor: gglm.NewVec3(1, 0, 0),
|
||||||
SpecularColor: gglm.NewVec3(1, 1, 1),
|
SpecularColor: gglm.NewVec3(1, 1, 1),
|
||||||
// These values are for 50m range
|
Falloff: 1.0,
|
||||||
Constant: 1.0,
|
Radius: 20,
|
||||||
Linear: 0.09,
|
|
||||||
Quadratic: 0.032,
|
|
||||||
|
|
||||||
FarPlane: 25,
|
FarPlane: 25,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pos: gglm.NewVec3(0, -5, 0),
|
Pos: gglm.NewVec3(0, -5, 0),
|
||||||
DiffuseColor: gglm.NewVec3(0, 1, 0),
|
DiffuseColor: gglm.NewVec3(0, 1, 0),
|
||||||
SpecularColor: gglm.NewVec3(1, 1, 1),
|
SpecularColor: gglm.NewVec3(1, 1, 1),
|
||||||
Constant: 1.0,
|
Falloff: 1.0,
|
||||||
Linear: 0.09,
|
Radius: 20,
|
||||||
Quadratic: 0.032,
|
|
||||||
FarPlane: 25,
|
FarPlane: 25,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pos: gglm.NewVec3(5, 0, 0),
|
Pos: gglm.NewVec3(5, 0, 0),
|
||||||
DiffuseColor: gglm.NewVec3(1, 1, 1),
|
DiffuseColor: gglm.NewVec3(1, 1, 1),
|
||||||
SpecularColor: gglm.NewVec3(1, 1, 1),
|
SpecularColor: gglm.NewVec3(1, 1, 1),
|
||||||
Constant: 1.0,
|
Falloff: 1.0,
|
||||||
Linear: 0.09,
|
Radius: 20,
|
||||||
Quadratic: 0.032,
|
|
||||||
FarPlane: 25,
|
FarPlane: 25,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pos: gglm.NewVec3(-3, 4, 3),
|
Pos: gglm.NewVec3(-3, 4, 3),
|
||||||
DiffuseColor: gglm.NewVec3(1, 1, 1),
|
DiffuseColor: gglm.NewVec3(1, 1, 1),
|
||||||
SpecularColor: gglm.NewVec3(1, 1, 1),
|
SpecularColor: gglm.NewVec3(1, 1, 1),
|
||||||
Constant: 1.0,
|
Falloff: 1.0,
|
||||||
Linear: 0.09,
|
Radius: 10,
|
||||||
Quadratic: 0.032,
|
|
||||||
FarPlane: 25,
|
FarPlane: 25,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -750,20 +740,15 @@ func (g *Game) updateLights() {
|
|||||||
groundMat.SetUnifVec3(indexString+".specularColor", &p.SpecularColor)
|
groundMat.SetUnifVec3(indexString+".specularColor", &p.SpecularColor)
|
||||||
palleteMat.SetUnifVec3(indexString+".specularColor", &p.SpecularColor)
|
palleteMat.SetUnifVec3(indexString+".specularColor", &p.SpecularColor)
|
||||||
|
|
||||||
whiteMat.SetUnifFloat32(indexString+".constant", p.Constant)
|
whiteMat.SetUnifFloat32(indexString+".falloff", p.Falloff)
|
||||||
containerMat.SetUnifFloat32(indexString+".constant", p.Constant)
|
containerMat.SetUnifFloat32(indexString+".falloff", p.Falloff)
|
||||||
groundMat.SetUnifFloat32(indexString+".constant", p.Constant)
|
groundMat.SetUnifFloat32(indexString+".falloff", p.Falloff)
|
||||||
palleteMat.SetUnifFloat32(indexString+".constant", p.Constant)
|
palleteMat.SetUnifFloat32(indexString+".falloff", p.Falloff)
|
||||||
|
|
||||||
whiteMat.SetUnifFloat32(indexString+".linear", p.Linear)
|
whiteMat.SetUnifFloat32(indexString+".radius", p.Radius)
|
||||||
containerMat.SetUnifFloat32(indexString+".linear", p.Linear)
|
containerMat.SetUnifFloat32(indexString+".radius", p.Radius)
|
||||||
groundMat.SetUnifFloat32(indexString+".linear", p.Linear)
|
groundMat.SetUnifFloat32(indexString+".radius", p.Radius)
|
||||||
palleteMat.SetUnifFloat32(indexString+".linear", p.Linear)
|
palleteMat.SetUnifFloat32(indexString+".radius", p.Radius)
|
||||||
|
|
||||||
whiteMat.SetUnifFloat32(indexString+".quadratic", p.Quadratic)
|
|
||||||
containerMat.SetUnifFloat32(indexString+".quadratic", p.Quadratic)
|
|
||||||
groundMat.SetUnifFloat32(indexString+".quadratic", p.Quadratic)
|
|
||||||
palleteMat.SetUnifFloat32(indexString+".quadratic", p.Quadratic)
|
|
||||||
|
|
||||||
whiteMat.SetUnifFloat32(indexString+".farPlane", p.FarPlane)
|
whiteMat.SetUnifFloat32(indexString+".farPlane", p.FarPlane)
|
||||||
containerMat.SetUnifFloat32(indexString+".farPlane", p.FarPlane)
|
containerMat.SetUnifFloat32(indexString+".farPlane", p.FarPlane)
|
||||||
@ -832,10 +817,6 @@ func (g *Game) Update() {
|
|||||||
g.updateCameraPos()
|
g.updateCameraPos()
|
||||||
|
|
||||||
g.showDebugWindow()
|
g.showDebugWindow()
|
||||||
|
|
||||||
if input.KeyClicked(sdl.K_F4) {
|
|
||||||
logging.InfoLog.Printf("Pos: %s; Forward: %s; |Forward|: %f\n", cam.Pos.String(), cam.Forward.String(), cam.Forward.Mag())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) showDebugWindow() {
|
func (g *Game) showDebugWindow() {
|
||||||
@ -957,24 +938,53 @@ func (g *Game) showDebugWindow() {
|
|||||||
indexString := "pointLights[" + indexNumString + "]"
|
indexString := "pointLights[" + indexNumString + "]"
|
||||||
|
|
||||||
if imgui.DragFloat3("Pos", &pl.Pos.Data) {
|
if imgui.DragFloat3("Pos", &pl.Pos.Data) {
|
||||||
whiteMat.SetUnifVec3(indexString+".pos", &pl.Pos)
|
|
||||||
containerMat.SetUnifVec3(indexString+".pos", &pl.Pos)
|
posStr := indexString + ".pos"
|
||||||
groundMat.SetUnifVec3(indexString+".pos", &pl.Pos)
|
|
||||||
palleteMat.SetUnifVec3(indexString+".pos", &pl.Pos)
|
whiteMat.SetUnifVec3(posStr, &pl.Pos)
|
||||||
|
containerMat.SetUnifVec3(posStr, &pl.Pos)
|
||||||
|
groundMat.SetUnifVec3(posStr, &pl.Pos)
|
||||||
|
palleteMat.SetUnifVec3(posStr, &pl.Pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
if imgui.ColorEdit3("Diffuse Color", &pl.DiffuseColor.Data) {
|
if imgui.ColorEdit3("Diffuse Color", &pl.DiffuseColor.Data) {
|
||||||
whiteMat.SetUnifVec3(indexString+".diffuseColor", &pl.DiffuseColor)
|
|
||||||
containerMat.SetUnifVec3(indexString+".diffuseColor", &pl.DiffuseColor)
|
diffStr := indexString + ".diffuseColor"
|
||||||
groundMat.SetUnifVec3(indexString+".diffuseColor", &pl.DiffuseColor)
|
|
||||||
palleteMat.SetUnifVec3(indexString+".diffuseColor", &pl.DiffuseColor)
|
whiteMat.SetUnifVec3(diffStr, &pl.DiffuseColor)
|
||||||
|
containerMat.SetUnifVec3(diffStr, &pl.DiffuseColor)
|
||||||
|
groundMat.SetUnifVec3(diffStr, &pl.DiffuseColor)
|
||||||
|
palleteMat.SetUnifVec3(diffStr, &pl.DiffuseColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
if imgui.ColorEdit3("Specular Color", &pl.SpecularColor.Data) {
|
if imgui.ColorEdit3("Specular Color", &pl.SpecularColor.Data) {
|
||||||
whiteMat.SetUnifVec3(indexString+".specularColor", &pl.SpecularColor)
|
|
||||||
containerMat.SetUnifVec3(indexString+".specularColor", &pl.SpecularColor)
|
specularStr := indexString + ".specularColor"
|
||||||
groundMat.SetUnifVec3(indexString+".specularColor", &pl.SpecularColor)
|
|
||||||
palleteMat.SetUnifVec3(indexString+".specularColor", &pl.SpecularColor)
|
whiteMat.SetUnifVec3(specularStr, &pl.SpecularColor)
|
||||||
|
containerMat.SetUnifVec3(specularStr, &pl.SpecularColor)
|
||||||
|
groundMat.SetUnifVec3(specularStr, &pl.SpecularColor)
|
||||||
|
palleteMat.SetUnifVec3(specularStr, &pl.SpecularColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if imgui.DragFloatV("Falloff", &pl.Falloff, 0.1, 0.001, 100, "%.3f", imgui.SliderFlagsNone) {
|
||||||
|
|
||||||
|
falloffStr := indexString + ".falloff"
|
||||||
|
|
||||||
|
whiteMat.SetUnifFloat32(falloffStr, pl.Falloff)
|
||||||
|
containerMat.SetUnifFloat32(falloffStr, pl.Falloff)
|
||||||
|
groundMat.SetUnifFloat32(falloffStr, pl.Falloff)
|
||||||
|
palleteMat.SetUnifFloat32(falloffStr, pl.Falloff)
|
||||||
|
}
|
||||||
|
|
||||||
|
if imgui.DragFloatV("Radius", &pl.Radius, 0.2, 0, 500, "%.3f", imgui.SliderFlagsNone) {
|
||||||
|
|
||||||
|
falloffStr := indexString + ".radius"
|
||||||
|
|
||||||
|
whiteMat.SetUnifFloat32(falloffStr, pl.Radius)
|
||||||
|
containerMat.SetUnifFloat32(falloffStr, pl.Radius)
|
||||||
|
groundMat.SetUnifFloat32(falloffStr, pl.Radius)
|
||||||
|
palleteMat.SetUnifFloat32(falloffStr, pl.Radius)
|
||||||
}
|
}
|
||||||
|
|
||||||
imgui.TreePop()
|
imgui.TreePop()
|
||||||
|
|||||||
@ -35,9 +35,8 @@ struct PointLight {
|
|||||||
vec3 pos;
|
vec3 pos;
|
||||||
vec3 diffuseColor;
|
vec3 diffuseColor;
|
||||||
vec3 specularColor;
|
vec3 specularColor;
|
||||||
float constant;
|
float falloff;
|
||||||
float linear;
|
float radius;
|
||||||
float quadratic;
|
|
||||||
float farPlane;
|
float farPlane;
|
||||||
};
|
};
|
||||||
uniform PointLight pointLights[NUM_POINT_LIGHTS];
|
uniform PointLight pointLights[NUM_POINT_LIGHTS];
|
||||||
@ -162,9 +161,8 @@ struct PointLight {
|
|||||||
vec3 pos;
|
vec3 pos;
|
||||||
vec3 diffuseColor;
|
vec3 diffuseColor;
|
||||||
vec3 specularColor;
|
vec3 specularColor;
|
||||||
float constant;
|
float falloff;
|
||||||
float linear;
|
float radius;
|
||||||
float quadratic;
|
|
||||||
float farPlane;
|
float farPlane;
|
||||||
};
|
};
|
||||||
uniform PointLight pointLights[NUM_POINT_LIGHTS];
|
uniform PointLight pointLights[NUM_POINT_LIGHTS];
|
||||||
@ -272,10 +270,60 @@ float CalcPointShadow(int lightIndex, vec3 worldLightPos, vec3 tangentLightDir,
|
|||||||
return shadow;
|
return shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// The following point light attenuation formulas
|
||||||
|
// are from https://lisyarus.github.io/blog/posts/point-light-attenuation.html
|
||||||
|
//
|
||||||
|
// I found them more intuitive than the standard implementation and it also ensures
|
||||||
|
// we have zero light at the selected distance.
|
||||||
|
//
|
||||||
|
float sqr(float x)
|
||||||
|
{
|
||||||
|
return x * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This version doesn't have a harsh cutoff at radius
|
||||||
|
float AttenuateNoCusp(float dist, float radius, float falloff)
|
||||||
|
{
|
||||||
|
// Since we only use this as attenuation and max intensity defines
|
||||||
|
// the max output value, anything more than 1 would increase
|
||||||
|
// the output of the light, which I don't think makes sense for
|
||||||
|
// our attenuation purposes.
|
||||||
|
//
|
||||||
|
// Seems to me this can be done simply by increasing color values above 255.
|
||||||
|
//
|
||||||
|
// Forcing to 1 for now.
|
||||||
|
#define MAX_INTENSITY 1
|
||||||
|
|
||||||
|
float s = dist / radius;
|
||||||
|
|
||||||
|
if (s >= 1.0)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
float s2 = sqr(s);
|
||||||
|
|
||||||
|
return MAX_INTENSITY * sqr(1 - s2) / (1 + falloff * s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This version has a harsh/immediate cutoff at radius
|
||||||
|
float AttenuateCusp(float dist, float radius, float falloff)
|
||||||
|
{
|
||||||
|
#define MAX_INTENSITY 1
|
||||||
|
|
||||||
|
float s = dist / radius;
|
||||||
|
|
||||||
|
if (s >= 1.0)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
float s2 = sqr(s);
|
||||||
|
|
||||||
|
return MAX_INTENSITY * sqr(1 - s2) / (1 + falloff * s);
|
||||||
|
}
|
||||||
|
|
||||||
vec3 CalcPointLight(PointLight pointLight, int lightIndex)
|
vec3 CalcPointLight(PointLight pointLight, int lightIndex)
|
||||||
{
|
{
|
||||||
// Ignore unset lights
|
// Ignore inactive lights
|
||||||
if (pointLight.constant == 0){
|
if (pointLight.radius == 0){
|
||||||
return vec3(0);
|
return vec3(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +341,7 @@ vec3 CalcPointLight(PointLight pointLight, int lightIndex)
|
|||||||
|
|
||||||
// Attenuation
|
// Attenuation
|
||||||
float distToLight = length(tangentLightPos - tangentFragPos);
|
float distToLight = length(tangentLightPos - tangentFragPos);
|
||||||
float attenuation = 1 / (pointLight.constant + pointLight.linear * distToLight + pointLight.quadratic * (distToLight * distToLight));
|
float attenuation = AttenuateNoCusp(distToLight, pointLight.radius, pointLight.falloff);
|
||||||
|
|
||||||
// Shadow
|
// Shadow
|
||||||
float shadow = CalcPointShadow(lightIndex, pointLight.pos, tangentLightDir, pointLight.farPlane);
|
float shadow = CalcPointShadow(lightIndex, pointLight.pos, tangentLightDir, pointLight.farPlane);
|
||||||
|
|||||||
Reference in New Issue
Block a user