From 7b1e3ea7b412072327d91bd43578643b574a1d3f Mon Sep 17 00:00:00 2001 From: bloeys Date: Sat, 11 May 2024 05:11:54 +0400 Subject: [PATCH] Default textures for diffuse/specular/normal/emission mat slots --- assets/textures.go | 9 +++++++ engine/engine.go | 56 ++++++++++++++++++++++++++++++++++++++++ main.go | 31 ++++------------------ materials/material.go | 52 +++++++++++++++++++++++-------------- res/shaders/simple.glsl | 19 +++++++------- res/textures/black.png | Bin 142 -> 0 bytes res/textures/white.png | Bin 232 -> 0 bytes 7 files changed, 112 insertions(+), 55 deletions(-) delete mode 100755 res/textures/black.png delete mode 100755 res/textures/white.png diff --git a/assets/textures.go b/assets/textures.go index 713895f..15f90ea 100755 --- a/assets/textures.go +++ b/assets/textures.go @@ -23,6 +23,15 @@ const ( ColorFormat_RGBA8 ) +var ( + DefaultBlackTexId Texture + DefaultWhiteTexId Texture + DefaultDiffuseTexId Texture + DefaultSpecularTexId Texture + DefaultNormalTexId Texture + DefaultEmissionTexId Texture +) + type Texture struct { // Path only exists for textures loaded from disk Path string diff --git a/engine/engine.go b/engine/engine.go index fca98db..5af6acd 100755 --- a/engine/engine.go +++ b/engine/engine.go @@ -1,10 +1,13 @@ package engine import ( + "image" + "image/color" "runtime" imgui "github.com/AllenDang/cimgui-go" "github.com/bloeys/nmage/assert" + "github.com/bloeys/nmage/assets" "github.com/bloeys/nmage/input" "github.com/bloeys/nmage/renderer" "github.com/bloeys/nmage/timing" @@ -202,6 +205,8 @@ func createWindow(title string, x, y, width, height int32, flags WindowFlags, re return win, err } + setupDefaultTextures() + // Get rid of the blinding white startup screen (unfortunately there is still one frame of white) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) win.SDLWin.GLSwap() @@ -231,6 +236,57 @@ func initOpenGL() error { return nil } +func setupDefaultTextures() error { + + // 1x1 black texture + defaultBlackImg := image.NewNRGBA(image.Rect(0, 0, 1, 1)) + defaultBlackImg.Set(0, 0, color.NRGBA{R: 0, G: 0, B: 0, A: 1}) + defaultBlackImgTex, err := assets.LoadTextureInMemPngImg(defaultBlackImg, &assets.TextureLoadOptions{NoSrgba: true}) + if err != nil { + return err + } + assets.DefaultBlackTexId = defaultBlackImgTex + + // 1x1 white texture + defaultWhiteImg := image.NewNRGBA(image.Rect(0, 0, 1, 1)) + defaultWhiteImg.Set(0, 0, color.NRGBA{R: 255, G: 255, B: 255, A: 1}) + defaultWhiteImgTex, err := assets.LoadTextureInMemPngImg(defaultWhiteImg, &assets.TextureLoadOptions{NoSrgba: true}) + if err != nil { + return err + } + assets.DefaultWhiteTexId = defaultWhiteImgTex + + // Default diffuse + assets.DefaultDiffuseTexId = defaultWhiteImgTex + + // Default specular + assets.DefaultSpecularTexId = defaultBlackImgTex + + // Default Normal map which is created to be RGB(0.5,0.5,1), which when multiplied by TBN matrix gives the vertex normal. + // 128 is better than 127 for normal maps. See 'Flat Color' section here: http://wiki.polycount.com/wiki/Normal_map + // Basically, 127 can create seams while 128 looks correct + defaultNormalMapImg := image.NewNRGBA(image.Rect(0, 0, 1, 1)) + defaultNormalMapImg.Set(0, 0, color.NRGBA{R: 128, G: 128, B: 255, A: 1}) + defaultNormalMapTex, err := assets.LoadTextureInMemPngImg(defaultNormalMapImg, &assets.TextureLoadOptions{NoSrgba: true}) + if err != nil { + return err + } + + assets.DefaultNormalTexId = defaultNormalMapTex + + // Default emission + assets.DefaultEmissionTexId = defaultBlackImgTex + + assert.T(assets.DefaultBlackTexId.TexID != 0, "The default black texture handle is zero. Either texture wasn't created or handle wasn't updated") + assert.T(assets.DefaultWhiteTexId.TexID != 0, "The default white texture handle is zero. Either texture wasn't created or handle wasn't updated") + assert.T(assets.DefaultDiffuseTexId.TexID != 0, "The default diffuse texture handle is zero. Either texture wasn't created or handle wasn't updated") + assert.T(assets.DefaultSpecularTexId.TexID != 0, "The default specular texture handle is zero. Either texture wasn't created or handle wasn't updated") + assert.T(assets.DefaultNormalTexId.TexID != 0, "The default normal texture handle is zero. Either texture wasn't created or handle wasn't updated") + assert.T(assets.DefaultEmissionTexId.TexID != 0, "The default emission texture handle is zero. Either texture wasn't created or handle wasn't updated") + + return nil +} + func SetSrgbFramebuffer(isEnabled bool) { if isEnabled { diff --git a/main.go b/main.go index 98e90e3..85bf852 100755 --- a/main.go +++ b/main.go @@ -475,16 +475,6 @@ func (g *Game) Init() { } //Load textures - whiteTex, err := assets.LoadTexturePNG("./res/textures/white.png", &assets.TextureLoadOptions{}) - if err != nil { - logging.ErrLog.Fatalln("Failed to load texture. Err: ", err) - } - - blackTex, err := assets.LoadTexturePNG("./res/textures/black.png", &assets.TextureLoadOptions{}) - if err != nil { - logging.ErrLog.Fatalln("Failed to load texture. Err: ", err) - } - containerDiffuseTex, err := assets.LoadTexturePNG("./res/textures/container-diffuse.png", &assets.TextureLoadOptions{}) if err != nil { logging.ErrLog.Fatalln("Failed to load texture. Err: ", err) @@ -505,7 +495,7 @@ func (g *Game) Init() { logging.ErrLog.Fatalln("Failed to load texture. Err: ", err) } - brickwallNormalTex, err := assets.LoadTexturePNG("./res/textures/brickwall-normal.png", &assets.TextureLoadOptions{}) + brickwallNormalTex, err := assets.LoadTexturePNG("./res/textures/brickwall-normal.png", &assets.TextureLoadOptions{NoSrgba: true}) if err != nil { logging.ErrLog.Fatalln("Failed to load texture. Err: ", err) } @@ -533,12 +523,8 @@ func (g *Game) Init() { unlitMat.SetUnifInt32("material.diffuse", int32(materials.TextureSlot_Diffuse)) whiteMat = materials.NewMaterial("White mat", "./res/shaders/simple.glsl") - whiteMat.Settings.Set(materials.MaterialSettings_HasModelMtx | materials.MaterialSettings_HasNormalMtx) + whiteMat.Settings.Set(materials.MaterialSettings_HasModelMtx) whiteMat.Shininess = 64 - whiteMat.DiffuseTex = whiteTex.TexID - whiteMat.SpecularTex = blackTex.TexID - whiteMat.NormalTex = blackTex.TexID - whiteMat.EmissionTex = blackTex.TexID whiteMat.SetUnifInt32("material.diffuse", int32(materials.TextureSlot_Diffuse)) whiteMat.SetUnifInt32("material.specular", int32(materials.TextureSlot_Specular)) whiteMat.SetUnifInt32("material.normal", int32(materials.TextureSlot_Normal)) @@ -553,12 +539,10 @@ func (g *Game) Init() { whiteMat.SetUnifInt32("spotLightShadowMaps", int32(materials.TextureSlot_ShadowMap_Array1)) containerMat = materials.NewMaterial("Container mat", "./res/shaders/simple.glsl") - containerMat.Settings.Set(materials.MaterialSettings_HasModelMtx | materials.MaterialSettings_HasNormalMtx) + containerMat.Settings.Set(materials.MaterialSettings_HasModelMtx) containerMat.Shininess = 64 containerMat.DiffuseTex = containerDiffuseTex.TexID containerMat.SpecularTex = containerSpecularTex.TexID - containerMat.NormalTex = blackTex.TexID - containerMat.EmissionTex = blackTex.TexID containerMat.SetUnifInt32("material.diffuse", int32(materials.TextureSlot_Diffuse)) containerMat.SetUnifInt32("material.specular", int32(materials.TextureSlot_Specular)) containerMat.SetUnifInt32("material.normal", int32(materials.TextureSlot_Normal)) @@ -573,12 +557,10 @@ func (g *Game) Init() { containerMat.SetUnifInt32("spotLightShadowMaps", int32(materials.TextureSlot_ShadowMap_Array1)) groundMat = materials.NewMaterial("Ground mat", "./res/shaders/simple.glsl") - groundMat.Settings.Set(materials.MaterialSettings_HasModelMtx | materials.MaterialSettings_HasNormalMtx) + groundMat.Settings.Set(materials.MaterialSettings_HasModelMtx) groundMat.Shininess = 64 groundMat.DiffuseTex = brickwallDiffuseTex.TexID - groundMat.SpecularTex = blackTex.TexID groundMat.NormalTex = brickwallNormalTex.TexID - groundMat.EmissionTex = blackTex.TexID groundMat.SetUnifInt32("material.diffuse", int32(materials.TextureSlot_Diffuse)) groundMat.SetUnifInt32("material.specular", int32(materials.TextureSlot_Specular)) groundMat.SetUnifInt32("material.normal", int32(materials.TextureSlot_Normal)) @@ -593,12 +575,9 @@ func (g *Game) Init() { groundMat.SetUnifInt32("spotLightShadowMaps", int32(materials.TextureSlot_ShadowMap_Array1)) palleteMat = materials.NewMaterial("Pallete mat", "./res/shaders/simple.glsl") - palleteMat.Settings.Set(materials.MaterialSettings_HasModelMtx | materials.MaterialSettings_HasNormalMtx) + palleteMat.Settings.Set(materials.MaterialSettings_HasModelMtx) palleteMat.Shininess = 64 palleteMat.DiffuseTex = palleteTex.TexID - palleteMat.SpecularTex = blackTex.TexID - palleteMat.NormalTex = blackTex.TexID - palleteMat.EmissionTex = blackTex.TexID palleteMat.SetUnifInt32("material.diffuse", int32(materials.TextureSlot_Diffuse)) palleteMat.SetUnifInt32("material.specular", int32(materials.TextureSlot_Specular)) palleteMat.SetUnifInt32("material.normal", int32(materials.TextureSlot_Normal)) diff --git a/materials/material.go b/materials/material.go index e1040ed..d55312e 100755 --- a/materials/material.go +++ b/materials/material.go @@ -3,6 +3,7 @@ package materials import ( "github.com/bloeys/gglm/gglm" "github.com/bloeys/nmage/assert" + "github.com/bloeys/nmage/assets" "github.com/bloeys/nmage/logging" "github.com/bloeys/nmage/shaders" "github.com/go-gl/gl/v4.1-core/gl" @@ -49,7 +50,7 @@ type Material struct { UnifLocs map[string]int32 AttribLocs map[string]int32 - // @TODO do this in a better way. Perhaps something like how we do fbo attachments + // @TODO: Do this in a better way?. Perhaps something like how we do fbo attachments? Or keep it? // Phong shading DiffuseTex uint32 SpecularTex uint32 @@ -72,26 +73,19 @@ func (m *Material) Bind() { m.ShaderProg.Bind() - if m.DiffuseTex != 0 { - gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Diffuse)) - gl.BindTexture(gl.TEXTURE_2D, m.DiffuseTex) - } + gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Diffuse)) + gl.BindTexture(gl.TEXTURE_2D, m.DiffuseTex) - if m.SpecularTex != 0 { - gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Specular)) - gl.BindTexture(gl.TEXTURE_2D, m.SpecularTex) - } + gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Specular)) + gl.BindTexture(gl.TEXTURE_2D, m.SpecularTex) - if m.NormalTex != 0 { - gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Normal)) - gl.BindTexture(gl.TEXTURE_2D, m.NormalTex) - } + gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Normal)) + gl.BindTexture(gl.TEXTURE_2D, m.NormalTex) - if m.EmissionTex != 0 { - gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Emission)) - gl.BindTexture(gl.TEXTURE_2D, m.EmissionTex) - } + gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Emission)) + gl.BindTexture(gl.TEXTURE_2D, m.EmissionTex) + // @TODO: Have defaults for these if m.CubemapTex != 0 { gl.ActiveTexture(uint32(gl.TEXTURE0 + TextureSlot_Cubemap)) gl.BindTexture(gl.TEXTURE_CUBE_MAP, m.CubemapTex) @@ -194,7 +188,17 @@ func NewMaterial(matName, shaderPath string) Material { logging.ErrLog.Fatalf("Failed to create new material '%s'. Err: %s\n", matName, err.Error()) } - return Material{Name: matName, ShaderProg: shdrProg, UnifLocs: make(map[string]int32), AttribLocs: make(map[string]int32)} + return Material{ + Name: matName, + ShaderProg: shdrProg, + UnifLocs: make(map[string]int32), + AttribLocs: make(map[string]int32), + + DiffuseTex: assets.DefaultDiffuseTexId.TexID, + SpecularTex: assets.DefaultSpecularTexId.TexID, + NormalTex: assets.DefaultNormalTexId.TexID, + EmissionTex: assets.DefaultEmissionTexId.TexID, + } } func NewMaterialSrc(matName string, shaderSrc []byte) Material { @@ -204,5 +208,15 @@ func NewMaterialSrc(matName string, shaderSrc []byte) Material { logging.ErrLog.Fatalf("Failed to create new material '%s'. Err: %s\n", matName, err.Error()) } - return Material{Name: matName, ShaderProg: shdrProg, UnifLocs: make(map[string]int32), AttribLocs: make(map[string]int32)} + return Material{ + Name: matName, + ShaderProg: shdrProg, + UnifLocs: make(map[string]int32), + AttribLocs: make(map[string]int32), + + DiffuseTex: assets.DefaultDiffuseTexId.TexID, + SpecularTex: assets.DefaultSpecularTexId.TexID, + NormalTex: assets.DefaultNormalTexId.TexID, + EmissionTex: assets.DefaultEmissionTexId.TexID, + } } diff --git a/res/shaders/simple.glsl b/res/shaders/simple.glsl index 52ad6fc..ad5f6e0 100755 --- a/res/shaders/simple.glsl +++ b/res/shaders/simple.glsl @@ -64,7 +64,6 @@ out vec4 fragPosSpotLight[NUM_SPOT_LIGHTS]; out vec3 tangentCamPos; out vec3 tangentFragPos; -out vec3 tangentVertNormal; out vec3 tangentDirLightDir; out vec3 tangentSpotLightPositions[NUM_SPOT_LIGHTS]; out vec3 tangentSpotLightDirections[NUM_SPOT_LIGHTS]; @@ -86,8 +85,6 @@ void main() vec3 B = cross(N, T); mat3 tbnMtx = transpose(mat3(T, B, N)); - tangentVertNormal = tbnMtx * normalMat * vertNormalIn; - // Lighting related fragPos = modelVert.xyz; fragPosDirLight = vec3(dirLightProjViewMat * vec4(fragPos, 1)); @@ -136,7 +133,6 @@ in vec4 fragPosSpotLight[NUM_SPOT_LIGHTS]; in vec3 tangentCamPos; in vec3 tangentFragPos; -in vec3 tangentVertNormal; in vec3 tangentDirLightDir; in vec3 tangentSpotLightPositions[NUM_SPOT_LIGHTS]; in vec3 tangentSpotLightDirections[NUM_SPOT_LIGHTS]; @@ -378,6 +374,8 @@ vec3 CalcSpotLight(SpotLight light, int lightIndex) return (finalDiffuse + finalSpecular) * intensity * (1 - shadow); } +#define DRAW_NORMALS false + void main() { // Shared values @@ -389,12 +387,8 @@ void main() // Read normal data encoded [0,1] normalizedVertNorm = texture(material.normal, vertUV0).rgb; - // Handle no normal map - if (normalizedVertNorm == vec3(0)) - normalizedVertNorm = normalize(tangentVertNormal); - else - // Remap normal to [-1,1] - normalizedVertNorm = normalize(normalizedVertNorm * 2.0 - 1.0); + // Remap normal to [-1,1] + normalizedVertNorm = normalize(normalizedVertNorm * 2.0 - 1.0); // Light contributions vec3 finalColor = CalcDirLight(); @@ -413,4 +407,9 @@ void main() vec3 finalAmbient = ambientColor * diffuseTexColor.rgb; fragColor = vec4(finalColor + finalAmbient + finalEmission, 1); + + if (DRAW_NORMALS) + { + fragColor = vec4(texture(material.normal, vertUV0).rgb, 1); + } } diff --git a/res/textures/black.png b/res/textures/black.png deleted file mode 100755 index 36c9240ce7c43ff0cdcb765507662a358bcda98f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=Dh+L6~vJ#O${~L1j-D$B+!?w+9({fxJTtzWe9$v$Fu1FfeB| Xqk#hhBTqv9SCEjWtDnm{r-UW|P2nHm diff --git a/res/textures/white.png b/res/textures/white.png deleted file mode 100755 index 13ae786a36388276f92874e58003887d0502ad40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1quc!CFrj$B>G+w-+`tGAQsgYzopr0N|cSCIA2c