tofu

Making something with OpenGL in Go
Log | Files | Refs

commit 897ac30c0e6ffed35b3536a1c2fec624797ec1b1
parent 1dad40f9d7f732011017b4c8f8c6b0e046047574
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Fri, 22 Nov 2024 16:55:29 +0900

use Program.Uniforms

Diffstat:
Mcmd/sample/fragment.glsl | 32++++++++++++++++----------------
Mcmd/sample/light_fragment.glsl | 4++--
Mcmd/sample/main.go | 108++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Mcmd/sample/teapot.glsl | 32++++++++++++++++----------------
Mshader.go | 40++++++++++++++++++++++++----------------
5 files changed, 124 insertions(+), 92 deletions(-)

diff --git a/cmd/sample/fragment.glsl b/cmd/sample/fragment.glsl @@ -1,9 +1,9 @@ #version 330 core -struct Material { - sampler2D diffuse; - sampler2D specular; - float shiness; +struct material { + sampler2D Diffuse; + sampler2D Specular; + float Shiness; }; struct DirLight { @@ -27,9 +27,9 @@ in vec3 fnormal; in vec3 fpos; in vec2 texPos; -uniform vec3 camPos; +uniform vec3 CamPos; uniform vec3 objCol; -uniform Material material; +uniform material Material; uniform DirLight Sun; uniform SpotLight Light; @@ -50,33 +50,33 @@ void main() { dist = length(Light.Pos - fpos); attenuation = 1 / (Light.Kc + Light.Kl * dist + Light.Kq * dist * dist); - ambient = vec3(texture(material.diffuse, texPos)) * Light.Ambient; + ambient = vec3(texture(Material.Diffuse, texPos)) * Light.Ambient; lightDir = normalize(Light.Pos - fpos); theta = dot(lightDir, normalize(-lightDir)); epsilon = Light.CutOff - Light.OuterCutOff; intensity = clamp((theta - Light.OuterCutOff) / epsilon, 0.0, 1.0); diff = max(dot(fnormal, lightDir), 0.0); - diffuse = diff * vec3(texture(material.diffuse, texPos)) * Light.Diffuse * intensity; + diffuse = diff * vec3(texture(Material.Diffuse, texPos)) * Light.Diffuse * intensity; - viewDir = normalize(camPos - fpos); + viewDir = normalize(CamPos - fpos); reflectDir = reflect(-lightDir, normalize(fnormal)); - spec = pow(max(dot(viewDir, reflectDir), 0), material.shiness); - specular = vec3(texture(material.specular, texPos)) * spec * Light.Specular * intensity; + spec = pow(max(dot(viewDir, reflectDir), 0), Material.Shiness); + specular = vec3(texture(Material.Specular, texPos)) * spec * Light.Specular * intensity; fcol += vec4(ambient + diffuse + specular, 0) * attenuation; - ambient = vec3(texture(material.diffuse, texPos)) * Sun.Ambient; + ambient = vec3(texture(Material.Diffuse, texPos)) * Sun.Ambient; lightDir = normalize(-Sun.Dir); diff = max(dot(fnormal, lightDir), 0.0); - diffuse = diff * vec3(texture(material.diffuse, texPos)) * Sun.Diffuse; + diffuse = diff * vec3(texture(Material.Diffuse, texPos)) * Sun.Diffuse; - viewDir = normalize(camPos - fpos); + viewDir = normalize(CamPos - fpos); reflectDir = reflect(-lightDir, fnormal); - spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shiness); - specular = vec3(texture(material.specular, texPos)) * spec * Sun.Specular; + spec = pow(max(dot(viewDir, reflectDir), 0.0), Material.Shiness); + specular = vec3(texture(Material.Specular, texPos)) * spec * Sun.Specular; fcol += vec4(ambient + diffuse + specular, 0); diff --git a/cmd/sample/light_fragment.glsl b/cmd/sample/light_fragment.glsl @@ -1,7 +1,7 @@ #version 330 core -uniform vec3 lightCol; +uniform vec3 LightCol; out vec4 fcol; void main() { - fcol = vec4(lightCol, 1.0); + fcol = vec4(LightCol, 1.0); } diff --git a/cmd/sample/main.go b/cmd/sample/main.go @@ -201,7 +201,6 @@ type Trans struct { Projection, View, Model tofu.Mat4 } -var teapotTrans = new(Trans) var cubeTrans = new(Trans) var cubePositions = []tofu.Vec3{ @@ -217,6 +216,53 @@ var cubePositions = []tofu.Vec3{ {-2.00, 0.92, 4.57}, } +type Material struct { + Diffuse tofu.Vec3 + Specular tofu.Vec3 + Shiness float32 +} + +type MaterialTexture struct { + Diffuse *tofu.Texture + Specular *tofu.Texture + Shiness float32 +} + +var cubeUniforms = struct { + CamPos tofu.Vec3 + Trans Trans + Material MaterialTexture + Sun *DirLight + Light *SpotLight +}{ + Material: MaterialTexture{Shiness: 32}, + Sun: sun, + Light: spotLight, +} + +var teapotUniforms = struct { + CamPos tofu.Vec3 + Trans Trans + Material Material + Sun *DirLight + Light *SpotLight +}{ + Material: Material{ + Diffuse: tofu.Vec3{0.3, 0.4, 0.4}, + Specular: tofu.Vec3{0.3, 0.4, 0.4}, + Shiness: 32, + }, + Sun: sun, + Light: spotLight, +} + +var lightUniforms = struct { + Trans Trans + LightCol tofu.Vec3 +}{ + LightCol: spotLight.Specular, +} + var alpha float32 = 0.2 type App struct { @@ -229,8 +275,6 @@ type App struct { camera *tofu.Camera termination bool startedAt time.Time - texture *tofu.Texture - specularMap *tofu.Texture } func (app *App) Update() error { @@ -251,36 +295,29 @@ func (app *App) Update() error { spotLight.Dir = tofu.Vec3{0, 0, 0}.Sub(spotLight.Pos) app.program.Use() - cubeTrans.View = view - cubeTrans.Projection = projection - app.program.SetVec3("camPos", camera.Pos) - app.program.SetTexture("material.diffuse", app.texture) - app.program.SetTexture("material.specular", app.specularMap) - app.program.SetFloat32("material.shiness", 32) + cubeUniforms.Trans.View = view + cubeUniforms.Trans.Projection = projection + cubeUniforms.CamPos = camera.Pos for _, p := range cubePositions { model := tofu.Translate(p.Inverse()) - cubeTrans.Model = model + cubeUniforms.Trans.Model = model app.program.SetUniforms() cube.Draw(app.program) } app.teapotProgram.Use() - teapotTrans.View = view - teapotTrans.Projection = projection - teapotTrans.Model = tofu.Translate(tofu.Vec3{0, 0, 0}). + teapotUniforms.Trans.View = view + teapotUniforms.Trans.Projection = projection + teapotUniforms.Trans.Model = tofu.Translate(tofu.Vec3{0, 0, 0}). Mul(tofu.Rotate(now, tofu.Vec3{0, 1, 0})). Mul(tofu.Scale(0.06)) - app.teapotProgram.SetVec3("camPos", camera.Pos) - app.teapotProgram.SetVec3("material.diffuse", tofu.Vec3{0.3, 0.4, 0.4}) - app.teapotProgram.SetVec3("material.specular", tofu.Vec3{0.3, 0.4, 0.4}) - app.teapotProgram.SetFloat32("material.shiness", 32) + teapotUniforms.CamPos = camera.Pos app.teapotProgram.SetUniforms() teapot.Draw(app.teapotProgram) app.lightProgram.Use() - app.lightProgram.SetMat4("Trans.View", view) - app.lightProgram.SetMat4("Trans.Projection", projection) - app.lightProgram.SetMat4("Trans.Model", lightModel) - app.lightProgram.SetVec3("lightCol", spotLight.Specular) + lightUniforms.Trans.View = view + lightUniforms.Trans.Projection = projection + lightUniforms.Trans.Model = lightModel app.lightProgram.SetUniforms() light.Draw(app.lightProgram) @@ -320,44 +357,31 @@ func main() { if err != nil { log.Fatal(err) } - teapot.SetNormals() + //teapot.SetNormals() teapot.Load() app.program, err = tofu.NewProgram(vpath, fpath) if err != nil { log.Fatalf("create shader program: %v", err) } - app.program.Uniforms = struct { - Sun *DirLight - Light *SpotLight - Trans *Trans - }{ - sun, - spotLight, - cubeTrans, - } + app.program.Uniforms = &cubeUniforms app.lightProgram, err = tofu.NewProgram(vpath, lightFpath) if err != nil { log.Fatalf("create light shader program: %v", err) } + app.lightProgram.Uniforms = &lightUniforms + app.teapotProgram, err = tofu.NewProgram(vpath, teapotFpath) if err != nil { log.Fatalf("create teapot shader program: %v", err) } - app.teapotProgram.Uniforms = struct { - Sun *DirLight - Light *SpotLight - Trans *Trans - }{ - Sun: sun, - Light: spotLight, - Trans: teapotTrans, - } - app.texture, err = tofu.NewTexture(texturePath) + app.teapotProgram.Uniforms = &teapotUniforms + + cubeUniforms.Material.Diffuse, err = tofu.NewTexture(texturePath) if err != nil { log.Fatalf("NewTesture: %v", err) } - app.specularMap, err = tofu.NewTexture(specularMapPath) + cubeUniforms.Material.Specular, err = tofu.NewTexture(specularMapPath) if err != nil { log.Fatalf("NewTesture: %v", err) } diff --git a/cmd/sample/teapot.glsl b/cmd/sample/teapot.glsl @@ -1,9 +1,9 @@ #version 330 core -struct Material { - vec3 diffuse; - vec3 specular; - float shiness; +struct material { + vec3 Diffuse; + vec3 Specular; + float Shiness; }; struct DirLight { @@ -27,9 +27,9 @@ in vec3 fnormal; in vec3 fpos; in vec2 texPos; -uniform vec3 camPos; +uniform vec3 CamPos; uniform vec3 objCol; -uniform Material material; +uniform material Material; uniform DirLight Sun; uniform SpotLight Light; @@ -50,33 +50,33 @@ void main() { dist = length(Light.Pos - fpos); attenuation = 1 / (Light.Kc + Light.Kl * dist + Light.Kq * dist * dist); - ambient = material.diffuse * Light.Ambient; + ambient = Material.Diffuse * Light.Ambient; lightDir = normalize(Light.Pos - fpos); theta = dot(lightDir, normalize(-Light.Dir)); epsilon = Light.CutOff - Light.OuterCutOff; intensity = clamp((theta - Light.OuterCutOff) / epsilon, 0.0, 1.0); diff = max(dot(fnormal, lightDir), 0.0); - diffuse = diff * material.diffuse * Light.Diffuse * intensity; + diffuse = diff * Material.Diffuse * Light.Diffuse * intensity; - viewDir = normalize(camPos - fpos); + viewDir = normalize(CamPos - fpos); reflectDir = reflect(-lightDir, fnormal); - spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shiness); - specular = material.specular * spec * Light.Specular * intensity; + spec = pow(max(dot(viewDir, reflectDir), 0.0), Material.Shiness); + specular = Material.Specular * spec * Light.Specular * intensity; fcol += vec4((ambient+diffuse+specular) * attenuation, 0); - ambient = material.diffuse * Sun.Ambient; + ambient = Material.Diffuse * Sun.Ambient; lightDir = normalize(-Sun.Dir); diff = max(dot(fnormal, lightDir), 0.0); - diffuse = diff * material.diffuse * Sun.Diffuse; + diffuse = diff * Material.Diffuse * Sun.Diffuse; - viewDir = normalize(camPos - fpos); + viewDir = normalize(CamPos - fpos); reflectDir = reflect(-lightDir, fnormal); - spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shiness); - specular = material.specular * spec * Sun.Specular; + spec = pow(max(dot(viewDir, reflectDir), 0.0), Material.Shiness); + specular = Material.Specular * spec * Sun.Specular; fcol += vec4(ambient + diffuse + specular, 0); } diff --git a/shader.go b/shader.go @@ -97,6 +97,9 @@ func (p *Program) setUniforms(uniforms any, prefix string) error { if uniforms == nil { return nil } + if reflect.TypeOf(uniforms).Kind() == reflect.Pointer { + uniforms = reflect.ValueOf(uniforms).Elem().Interface() + } s := reflect.ValueOf(uniforms) fields := reflect.VisibleFields(s.Type()) for i := 0; i < s.NumField(); i++ { @@ -109,33 +112,38 @@ func (p *Program) setUniforms(uniforms any, prefix string) error { if prefix != "" { tag = prefix + "." + tag } - switch fv.Kind() { - case reflect.Struct: - if err := p.setUniforms(fv.Interface(), tag); err != nil { - return err - } - continue - case reflect.Pointer: - if err := p.setUniforms(fv.Elem().Interface(), tag); err != nil { - return err - } - continue - } switch ft.Type.String() { case "tofu.Mat4": if err := p.SetMat4(tag, fv.Interface().(Mat4)); err != nil { - return err + return fmt.Errorf("set %s: %v", tag, err) } case "tofu.Vec3": if err := p.SetVec3(tag, fv.Interface().(Vec3)); err != nil { - return err + return fmt.Errorf("set %s: %v", tag, err) } case "float32": if err := p.SetFloat32(tag, fv.Interface().(float32)); err != nil { - return err + return fmt.Errorf("set %s: %v", tag, err) + } + case "*tofu.Texture": + if err := p.SetTexture(tag, fv.Interface().(*Texture)); err != nil { + return fmt.Errorf("set %s: %v", tag, err) } default: - return fmt.Errorf("unknown uniform type: %s", ft.Type) + switch fv.Kind() { + case reflect.Struct: + if err := p.setUniforms(fv.Interface(), tag); err != nil { + return err + } + continue + case reflect.Pointer: + if err := p.setUniforms(fv.Elem().Interface(), tag); err != nil { + return err + } + continue + default: + return fmt.Errorf("unknown uniform type: %s", ft.Type) + } } } return nil