mirror of
https://github.com/bloeys/nmage.git
synced 2025-12-29 13:28:20 +00:00
Compare commits
1 Commits
c00f6d97dd
...
v0.19.8
| Author | SHA1 | Date | |
|---|---|---|---|
| 83922f1908 |
145
main.go
145
main.go
@ -26,9 +26,10 @@ import (
|
||||
/*
|
||||
@TODO:
|
||||
- Rendering:
|
||||
- Phong lighting model
|
||||
- Point lights
|
||||
- Spotlights
|
||||
- Phong lighting model ✅
|
||||
- Directional lights ✅
|
||||
- Point lights ✅
|
||||
- Spotlights ✅
|
||||
- HDR
|
||||
- Cascaded shadow mapping
|
||||
- Skeletal animations
|
||||
@ -62,6 +63,7 @@ type PointLight struct {
|
||||
}
|
||||
|
||||
type SpotLight struct {
|
||||
Pos gglm.Vec3
|
||||
Dir gglm.Vec3
|
||||
DiffuseColor gglm.Vec3
|
||||
SpecularColor gglm.Vec3
|
||||
@ -69,6 +71,18 @@ type SpotLight struct {
|
||||
OuterCutoff float32
|
||||
}
|
||||
|
||||
// SetCutoffs properly sets the cosine values of the cutoffs using the passed
|
||||
// degrees.
|
||||
//
|
||||
// The light has full intensity within the inner cutoff, falloff between
|
||||
// inner-outer cutoff, and zero light beyond the outer cutoff.
|
||||
//
|
||||
// The inner cuttoff degree must be *smaller* than the outer cutoff
|
||||
func (s *SpotLight) SetCutoffs(innerCutoffAngleDeg, outerCutoffAngleDeg float32) {
|
||||
s.InnerCutoff = gglm.Cos32(innerCutoffAngleDeg * gglm.Deg2Rad)
|
||||
s.OuterCutoff = gglm.Cos32(outerCutoffAngleDeg * gglm.Deg2Rad)
|
||||
}
|
||||
|
||||
const (
|
||||
camSpeed = 15
|
||||
mouseSensitivity = 0.5
|
||||
@ -148,6 +162,17 @@ var (
|
||||
Quadratic: 0.032,
|
||||
},
|
||||
}
|
||||
spotLights = [...]SpotLight{
|
||||
{
|
||||
Pos: *gglm.NewVec3(0, 5, 0),
|
||||
Dir: *gglm.NewVec3(0, -1, 0),
|
||||
DiffuseColor: *gglm.NewVec3(0, 1, 1),
|
||||
SpecularColor: *gglm.NewVec3(1, 1, 1),
|
||||
// These must be cosine values
|
||||
InnerCutoff: gglm.Cos32(15 * gglm.Deg2Rad),
|
||||
OuterCutoff: gglm.Cos32(20 * gglm.Deg2Rad),
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type Game struct {
|
||||
@ -456,6 +481,36 @@ func (g *Game) updateLights() {
|
||||
containerMat.SetUnifFloat32(indexString+".quadratic", pl.Quadratic)
|
||||
palleteMat.SetUnifFloat32(indexString+".quadratic", pl.Quadratic)
|
||||
}
|
||||
|
||||
for i := 0; i < len(spotLights); i++ {
|
||||
|
||||
l := &spotLights[i]
|
||||
indexString := "spotLights[" + strconv.Itoa(i) + "]"
|
||||
|
||||
whiteMat.SetUnifVec3(indexString+".pos", &l.Pos)
|
||||
containerMat.SetUnifVec3(indexString+".pos", &l.Pos)
|
||||
palleteMat.SetUnifVec3(indexString+".pos", &l.Pos)
|
||||
|
||||
whiteMat.SetUnifVec3(indexString+".dir", &l.Dir)
|
||||
containerMat.SetUnifVec3(indexString+".dir", &l.Dir)
|
||||
palleteMat.SetUnifVec3(indexString+".dir", &l.Dir)
|
||||
|
||||
whiteMat.SetUnifVec3(indexString+".diffuseColor", &l.DiffuseColor)
|
||||
containerMat.SetUnifVec3(indexString+".diffuseColor", &l.DiffuseColor)
|
||||
palleteMat.SetUnifVec3(indexString+".diffuseColor", &l.DiffuseColor)
|
||||
|
||||
whiteMat.SetUnifVec3(indexString+".specularColor", &l.SpecularColor)
|
||||
containerMat.SetUnifVec3(indexString+".specularColor", &l.SpecularColor)
|
||||
palleteMat.SetUnifVec3(indexString+".specularColor", &l.SpecularColor)
|
||||
|
||||
whiteMat.SetUnifFloat32(indexString+".innerCutoff", l.InnerCutoff)
|
||||
containerMat.SetUnifFloat32(indexString+".innerCutoff", l.InnerCutoff)
|
||||
palleteMat.SetUnifFloat32(indexString+".innerCutoff", l.InnerCutoff)
|
||||
|
||||
whiteMat.SetUnifFloat32(indexString+".outerCutoff", l.OuterCutoff)
|
||||
containerMat.SetUnifFloat32(indexString+".outerCutoff", l.OuterCutoff)
|
||||
palleteMat.SetUnifFloat32(indexString+".outerCutoff", l.OuterCutoff)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Game) Update() {
|
||||
@ -544,35 +599,91 @@ func (g *Game) showDebugWindow() {
|
||||
imgui.Spacing()
|
||||
|
||||
// Point lights
|
||||
imgui.Text("Point Lights")
|
||||
|
||||
if imgui.BeginListBoxV("", imgui.Vec2{Y: 200}) {
|
||||
if imgui.BeginListBoxV("Point Lights", imgui.Vec2{Y: 200}) {
|
||||
|
||||
for i := 0; i < len(pointLights); i++ {
|
||||
|
||||
pl := &pointLights[i]
|
||||
indexString := strconv.Itoa(i)
|
||||
indexNumString := strconv.Itoa(i)
|
||||
|
||||
if !imgui.TreeNodeExStrV("Light "+indexString, imgui.TreeNodeFlagsSpanAvailWidth) {
|
||||
if !imgui.TreeNodeExStrV("Point Light "+indexNumString, imgui.TreeNodeFlagsSpanAvailWidth) {
|
||||
continue
|
||||
}
|
||||
|
||||
indexString := "pointLights[" + indexNumString + "]"
|
||||
|
||||
if imgui.DragFloat3("Pos", &pl.Pos.Data) {
|
||||
whiteMat.SetUnifVec3("pointLights["+indexString+"].pos", &pl.Pos)
|
||||
containerMat.SetUnifVec3("pointLights["+indexString+"].pos", &pl.Pos)
|
||||
palleteMat.SetUnifVec3("pointLights["+indexString+"].pos", &pl.Pos)
|
||||
whiteMat.SetUnifVec3(indexString+".pos", &pl.Pos)
|
||||
containerMat.SetUnifVec3(indexString+".pos", &pl.Pos)
|
||||
palleteMat.SetUnifVec3(indexString+".pos", &pl.Pos)
|
||||
}
|
||||
|
||||
if imgui.DragFloat3("Diffuse Color", &pl.DiffuseColor.Data) {
|
||||
whiteMat.SetUnifVec3("pointLights["+indexString+"].diffuseColor", &pl.DiffuseColor)
|
||||
containerMat.SetUnifVec3("pointLights["+indexString+"].diffuseColor", &pl.DiffuseColor)
|
||||
palleteMat.SetUnifVec3("pointLights["+indexString+"].diffuseColor", &pl.DiffuseColor)
|
||||
whiteMat.SetUnifVec3(indexString+".diffuseColor", &pl.DiffuseColor)
|
||||
containerMat.SetUnifVec3(indexString+".diffuseColor", &pl.DiffuseColor)
|
||||
palleteMat.SetUnifVec3(indexString+".diffuseColor", &pl.DiffuseColor)
|
||||
}
|
||||
|
||||
if imgui.DragFloat3("Specular Color", &pl.SpecularColor.Data) {
|
||||
whiteMat.SetUnifVec3("pointLights["+indexString+"].specularColor", &pl.SpecularColor)
|
||||
containerMat.SetUnifVec3("pointLights["+indexString+"].specularColor", &pl.SpecularColor)
|
||||
palleteMat.SetUnifVec3("pointLights["+indexString+"].specularColor", &pl.SpecularColor)
|
||||
whiteMat.SetUnifVec3(indexString+".specularColor", &pl.SpecularColor)
|
||||
containerMat.SetUnifVec3(indexString+".specularColor", &pl.SpecularColor)
|
||||
palleteMat.SetUnifVec3(indexString+".specularColor", &pl.SpecularColor)
|
||||
}
|
||||
|
||||
imgui.TreePop()
|
||||
}
|
||||
|
||||
imgui.EndListBox()
|
||||
}
|
||||
|
||||
// Spot lights
|
||||
if imgui.BeginListBoxV("Spot Lights", imgui.Vec2{Y: 200}) {
|
||||
|
||||
for i := 0; i < len(spotLights); i++ {
|
||||
|
||||
l := &spotLights[i]
|
||||
indexNumString := strconv.Itoa(i)
|
||||
|
||||
if !imgui.TreeNodeExStrV("Spot Light "+indexNumString, imgui.TreeNodeFlagsSpanAvailWidth) {
|
||||
continue
|
||||
}
|
||||
|
||||
indexString := "spotLights[" + indexNumString + "]"
|
||||
|
||||
if imgui.DragFloat3("Pos", &l.Pos.Data) {
|
||||
whiteMat.SetUnifVec3(indexString+".pos", &l.Pos)
|
||||
containerMat.SetUnifVec3(indexString+".pos", &l.Pos)
|
||||
palleteMat.SetUnifVec3(indexString+".pos", &l.Pos)
|
||||
}
|
||||
|
||||
if imgui.DragFloat3("Dir", &l.Dir.Data) {
|
||||
whiteMat.SetUnifVec3(indexString+".dir", &l.Dir)
|
||||
containerMat.SetUnifVec3(indexString+".dir", &l.Dir)
|
||||
palleteMat.SetUnifVec3(indexString+".dir", &l.Dir)
|
||||
}
|
||||
|
||||
if imgui.DragFloat3("Diffuse Color", &l.DiffuseColor.Data) {
|
||||
whiteMat.SetUnifVec3(indexString+".diffuseColor", &l.DiffuseColor)
|
||||
containerMat.SetUnifVec3(indexString+".diffuseColor", &l.DiffuseColor)
|
||||
palleteMat.SetUnifVec3(indexString+".diffuseColor", &l.DiffuseColor)
|
||||
}
|
||||
|
||||
if imgui.DragFloat3("Specular Color", &l.SpecularColor.Data) {
|
||||
whiteMat.SetUnifVec3(indexString+".specularColor", &l.SpecularColor)
|
||||
containerMat.SetUnifVec3(indexString+".specularColor", &l.SpecularColor)
|
||||
palleteMat.SetUnifVec3(indexString+".specularColor", &l.SpecularColor)
|
||||
}
|
||||
|
||||
if imgui.DragFloat("Inner Cutoff", &l.InnerCutoff) {
|
||||
whiteMat.SetUnifFloat32(indexString+".innerCutoff", l.InnerCutoff)
|
||||
containerMat.SetUnifFloat32(indexString+".innerCutoff", l.InnerCutoff)
|
||||
palleteMat.SetUnifFloat32(indexString+".innerCutoff", l.InnerCutoff)
|
||||
}
|
||||
|
||||
if imgui.DragFloat("Outer Cutoff", &l.OuterCutoff) {
|
||||
whiteMat.SetUnifFloat32(indexString+".outerCutoff", l.OuterCutoff)
|
||||
containerMat.SetUnifFloat32(indexString+".outerCutoff", l.OuterCutoff)
|
||||
palleteMat.SetUnifFloat32(indexString+".outerCutoff", l.OuterCutoff)
|
||||
}
|
||||
|
||||
imgui.TreePop()
|
||||
|
||||
@ -64,6 +64,18 @@ struct PointLight {
|
||||
#define NUM_POINT_LIGHTS 16
|
||||
uniform PointLight pointLights[NUM_POINT_LIGHTS];
|
||||
|
||||
struct SpotLight {
|
||||
vec3 pos;
|
||||
vec3 dir;
|
||||
vec3 diffuseColor;
|
||||
vec3 specularColor;
|
||||
float innerCutoff;
|
||||
float outerCutoff;
|
||||
};
|
||||
|
||||
#define NUM_SPOT_LIGHTS 4
|
||||
uniform SpotLight spotLights[NUM_SPOT_LIGHTS];
|
||||
|
||||
uniform vec3 camPos;
|
||||
uniform vec3 ambientColor = vec3(0.2, 0.2, 0.2);
|
||||
|
||||
@ -122,9 +134,33 @@ vec3 CalcPointLight(PointLight pointLight)
|
||||
return (finalDiffuse + finalSpecular) * attenuation;
|
||||
}
|
||||
|
||||
vec3 CalcSpotLight()
|
||||
vec3 CalcSpotLight(SpotLight light)
|
||||
{
|
||||
return vec3(0);
|
||||
if (light.innerCutoff == 0)
|
||||
return vec3(0);
|
||||
|
||||
vec3 fragToLightDir = normalize(light.pos - fragPos);
|
||||
|
||||
// Spot light cone with full intensity within inner cutoff,
|
||||
// and falloff between inner-outer cutoffs, and zero
|
||||
// light after outer cutoff
|
||||
float theta = dot(fragToLightDir, normalize(-light.dir));
|
||||
float epsilon = (light.innerCutoff - light.outerCutoff);
|
||||
float intensity = clamp((theta - light.outerCutoff) / epsilon, 0.0, 1.0);
|
||||
|
||||
if (intensity == 0)
|
||||
return vec3(0);
|
||||
|
||||
// Diffuse
|
||||
float diffuseAmount = max(0.0, dot(normalizedVertNorm, fragToLightDir));
|
||||
vec3 finalDiffuse = diffuseAmount * light.diffuseColor * diffuseTexColor.rgb;
|
||||
|
||||
// Specular
|
||||
vec3 reflectDir = reflect(-fragToLightDir, normalizedVertNorm);
|
||||
float specularAmount = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
vec3 finalSpecular = specularAmount * light.specularColor * specularTexColor.rgb;
|
||||
|
||||
return (finalDiffuse + finalSpecular) * intensity;
|
||||
}
|
||||
|
||||
void main()
|
||||
@ -145,7 +181,10 @@ void main()
|
||||
finalColor += CalcPointLight(pointLights[i]);
|
||||
}
|
||||
|
||||
finalColor += CalcSpotLight();
|
||||
for (int i = 0; i < NUM_SPOT_LIGHTS; i++)
|
||||
{
|
||||
finalColor += CalcSpotLight(spotLights[i]);
|
||||
}
|
||||
|
||||
vec3 finalEmission = emissionTexColor.rgb;
|
||||
vec3 finalAmbient = ambientColor * diffuseTexColor.rgb;
|
||||
|
||||
Reference in New Issue
Block a user