Sfoglia il codice sorgente

Various fixes and improvements

Daniel Salvadori 3 anni fa
parent
commit
7b89285c3b

+ 2 - 1
app/app-browser.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build wasm
 // +build wasm
 
 package app
@@ -30,7 +31,7 @@ type Application struct {
 }
 
 // App returns the Application singleton, creating it the first time.
-func App() *Application {
+func App(width, height, title) *Application {
 
 	// Return singleton if already created
 	if a != nil {

+ 2 - 8
app/app-desktop.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !wasm
 // +build !wasm
 
 package app
@@ -16,13 +17,6 @@ import (
 	"github.com/g3n/engine/window"
 )
 
-// Desktop application defaults
-const (
-	title  = "G3N Application"
-	width  = 800
-	height = 600
-)
-
 // Application
 type Application struct {
 	window.IWindow                    // Embedded GlfwWindow
@@ -35,7 +29,7 @@ type Application struct {
 }
 
 // App returns the Application singleton, creating it the first time.
-func App() *Application {
+func App(width, height int, title string) *Application {
 
 	// Return singleton if already created
 	if a != nil {

+ 1 - 0
audio/audio_file.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !wasm
 // +build !wasm
 
 package audio

+ 1 - 0
audio/listener-browser.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build wasm
 // +build wasm
 
 package audio

+ 1 - 0
audio/listener-desktop.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !wasm
 // +build !wasm
 
 package audio

+ 28 - 29
audio/player.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !wasm
 // +build !wasm
 
 package audio
@@ -96,10 +97,6 @@ func (p *Player) State() int {
 func (p *Player) Play() error {
 
 	state := p.State()
-	// Already playing, nothing to do
-	if state == al.Playing {
-		return nil
-	}
 
 	// If paused, goroutine should be running, just starts playing
 	if state == al.Paused {
@@ -107,37 +104,39 @@ func (p *Player) Play() error {
 		return nil
 	}
 
-	// Inactive or Stopped state
-	if state == al.Initial || state == al.Stopped {
+	// Already playing - stop in order to start from beginning
+	if state == al.Playing {
+		p.Stop()
+	}
 
-		// Sets file pointer to the beginning
-		err := p.af.Seek(0)
-		if err != nil {
-			return err
-		}
+	// Sets file pointer to the beginning
+	err := p.af.Seek(0)
+	if err != nil {
+		return err
+	}
 
-		// Fill buffers with decoded data
-		for i := 0; i < playerBufferCount; i++ {
-			err = p.fillBuffer(p.buffers[i])
-			if err != nil {
-				if err != io.EOF {
-					return err
-				}
-				break
+	// Fill buffers with decoded data
+	for i := 0; i < playerBufferCount; i++ {
+		err = p.fillBuffer(p.buffers[i])
+		if err != nil {
+			if err != io.EOF {
+				return err
 			}
+			break
 		}
-		p.nextBuf = 0
+	}
+	p.nextBuf = 0
 
-		// Clear previous goroutine response channel
-		select {
-		case _ = <-p.gchan:
-		default:
-		}
-		// Starts playing and starts goroutine to fill buffers
-		al.SourcePlay(p.source)
-		go p.run()
-		return nil
+	// Clear previous goroutine response channel
+	select {
+	case _ = <-p.gchan:
+	default:
 	}
+
+	// Starts playing and starts goroutine to fill buffers
+	al.SourcePlay(p.source)
+	go p.run()
+	
 	return nil
 }
 

+ 2 - 0
camera/camera.go

@@ -62,6 +62,7 @@ func NewPerspective(aspect, near, far, fov float32, axis Axis) *Camera {
 
 	c := new(Camera)
 	c.Node.Init(c)
+	c.SetDirection(0, 0, -1)
 	c.aspect = aspect
 	c.near = near
 	c.far = far
@@ -78,6 +79,7 @@ func NewOrthographic(aspect, near, far, size float32, axis Axis) *Camera {
 
 	c := new(Camera)
 	c.Node.Init(c)
+	c.SetDirection(0, 0, -1)
 	c.aspect = aspect
 	c.near = near
 	c.far = far

+ 1 - 0
gls/gls-browser.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build wasm
 // +build wasm
 
 package gls

+ 1 - 1
gui/panel.go

@@ -592,7 +592,7 @@ func (p *Panel) Intersects(other *Panel) bool {
 }
 
 // SetEnabled sets the panel enabled state
-// A disabled panel do not process key or mouse events.
+// A disabled panel does not process events.
 func (p *Panel) SetEnabled(state bool) {
 
 	p.enabled = state

+ 16 - 0
gui/slider.go

@@ -163,6 +163,10 @@ func (s *Slider) setPos(pos float32) {
 // onMouse process subscribed mouse events over the outer panel
 func (s *Slider) onMouse(evname string, ev interface{}) {
 
+	if !s.Enabled() {
+		return
+	}
+
 	mev := ev.(*window.MouseEvent)
 	if mev.Button != window.MouseButtonLeft {
 		return
@@ -188,6 +192,10 @@ func (s *Slider) onMouse(evname string, ev interface{}) {
 // onCursor process subscribed cursor events
 func (s *Slider) onCursor(evname string, ev interface{}) {
 
+	if !s.Enabled() {
+		return
+	}
+
 	if evname == OnCursorEnter {
 		s.cursorOver = true
 		if s.horiz {
@@ -224,6 +232,10 @@ func (s *Slider) onCursor(evname string, ev interface{}) {
 // onScroll process subscribed scroll events
 func (s *Slider) onScroll(evname string, ev interface{}) {
 
+	if !s.Enabled() {
+		return
+	}
+
 	sev := ev.(*window.ScrollEvent)
 	v := s.pos
 	v += sev.Yoffset * 0.01
@@ -233,6 +245,10 @@ func (s *Slider) onScroll(evname string, ev interface{}) {
 // onKey process subscribed key events
 func (s *Slider) onKey(evname string, ev interface{}) {
 
+	if !s.Enabled() {
+		return
+	}
+
 	kev := ev.(*window.KeyEvent)
 	delta := float32(0.01)
 	// Horizontal slider

+ 404 - 404
renderer/shaders/sources.go

@@ -4,13 +4,28 @@
 
 package shaders
 
-const include_attributes_source = `//
-// Vertex attributes
-//
-layout(location = 0) in  vec3  VertexPosition;
-layout(location = 1) in  vec3  VertexNormal;
-layout(location = 2) in  vec3  VertexColor;
-layout(location = 3) in  vec2  VertexTexcoord;
+const include_morphtarget_vertex2_source = `	vPosition += MorphPosition{i} * morphTargetInfluences[{i}];
+  #ifdef MORPHTARGETS_NORMAL
+	vNormal += MorphNormal{i} * morphTargetInfluences[{i}];
+  #endif`
+
+const include_morphtarget_vertex_declaration2_source = `	in vec3 MorphPosition{i};
+  #ifdef MORPHTARGETS_NORMAL
+	in vec3 MorphNormal{i};
+  #endif
+`
+
+const include_morphtarget_vertex_source = `#ifdef MORPHTARGETS
+
+    #include <morphtarget_vertex2> [MORPHTARGETS]
+
+#endif
+`
+
+const include_morphtarget_vertex_declaration_source = `#ifdef MORPHTARGETS
+	uniform float morphTargetInfluences[MORPHTARGETS];
+	#include <morphtarget_vertex_declaration2> [MORPHTARGETS]
+#endif
 `
 
 const include_bones_vertex_source = `#ifdef BONE_INFLUENCERS
@@ -45,123 +60,6 @@ const include_bones_vertex_source = `#ifdef BONE_INFLUENCERS
 #endif
 `
 
-const include_bones_vertex_declaration_source = `#ifdef BONE_INFLUENCERS
-    #if BONE_INFLUENCERS > 0
-	uniform mat4 mBones[TOTAL_BONES];
-    in vec4 matricesIndices;
-    in vec4 matricesWeights;
-//    #if BONE_INFLUENCERS > 4
-//        in vec4 matricesIndicesExtra;
-//        in vec4 matricesWeightsExtra;
-//    #endif
-    #endif
-#endif
-`
-
-const include_lights_source = `//
-// Lights uniforms
-//
-
-#if AMB_LIGHTS>0
-    // Ambient lights color uniform
-    uniform vec3 AmbientLightColor[AMB_LIGHTS];
-#endif
-
-#if DIR_LIGHTS>0
-    // Directional lights uniform array. Each directional light uses 2 elements
-    uniform vec3 DirLight[2*DIR_LIGHTS];
-    // Macros to access elements inside the DirectionalLight uniform array
-    #define DirLightColor(a)		DirLight[2*a]
-    #define DirLightPosition(a)		DirLight[2*a+1]
-#endif
-
-#if POINT_LIGHTS>0
-    // Point lights uniform array. Each point light uses 3 elements
-    uniform vec3 PointLight[3*POINT_LIGHTS];
-    // Macros to access elements inside the PointLight uniform array
-    #define PointLightColor(a)			PointLight[3*a]
-    #define PointLightPosition(a)		PointLight[3*a+1]
-    #define PointLightLinearDecay(a)	PointLight[3*a+2].x
-    #define PointLightQuadraticDecay(a)	PointLight[3*a+2].y
-#endif
-
-#if SPOT_LIGHTS>0
-    // Spot lights uniforms. Each spot light uses 5 elements
-    uniform vec3  SpotLight[5*SPOT_LIGHTS];
-    // Macros to access elements inside the PointLight uniform array
-    #define SpotLightColor(a)			SpotLight[5*a]
-    #define SpotLightPosition(a)		SpotLight[5*a+1]
-    #define SpotLightDirection(a)		SpotLight[5*a+2]
-    #define SpotLightAngularDecay(a)	SpotLight[5*a+3].x
-    #define SpotLightCutoffAngle(a)		SpotLight[5*a+3].y
-    #define SpotLightLinearDecay(a)		SpotLight[5*a+3].z
-    #define SpotLightQuadraticDecay(a)	SpotLight[5*a+4].x
-#endif
-`
-
-const include_material_source = `//
-// Material properties uniform
-//
-
-// Material parameters uniform array
-uniform vec3 Material[6];
-// Macros to access elements inside the Material array
-#define MatAmbientColor		Material[0]
-#define MatDiffuseColor     Material[1]
-#define MatSpecularColor    Material[2]
-#define MatEmissiveColor    Material[3]
-#define MatShininess        Material[4].x
-#define MatOpacity          Material[4].y
-#define MatPointSize        Material[4].z
-#define MatPointRotationZ   Material[5].x
-
-#if MAT_TEXTURES > 0
-    // Texture unit sampler array
-    uniform sampler2D MatTexture[MAT_TEXTURES];
-    // Texture parameters (3*vec2 per texture)
-    uniform vec2 MatTexinfo[3*MAT_TEXTURES];
-    // Macros to access elements inside the MatTexinfo array
-    #define MatTexOffset(a)		MatTexinfo[(3*a)]
-    #define MatTexRepeat(a)		MatTexinfo[(3*a)+1]
-    #define MatTexFlipY(a)		bool(MatTexinfo[(3*a)+2].x)
-    #define MatTexVisible(a)	bool(MatTexinfo[(3*a)+2].y)
-    // Alpha compositing (see here: https://ciechanow.ski/alpha-compositing/)
-    vec4 Blend(vec4 texMixed, vec4 texColor) {
-        texMixed.rgb *= texMixed.a;
-        texColor.rgb *= texColor.a;
-        texMixed = texColor + texMixed * (1 - texColor.a);
-        if (texMixed.a > 0.0) {
-            texMixed.rgb /= texMixed.a;
-        }
-        return texMixed;
-    }
-#endif
-`
-
-const include_morphtarget_vertex_source = `#ifdef MORPHTARGETS
-
-    #include <morphtarget_vertex2> [MORPHTARGETS]
-
-#endif
-`
-
-const include_morphtarget_vertex2_source = `	vPosition += MorphPosition{i} * morphTargetInfluences[{i}];
-  #ifdef MORPHTARGETS_NORMAL
-	vNormal += MorphNormal{i} * morphTargetInfluences[{i}];
-  #endif`
-
-const include_morphtarget_vertex_declaration_source = `#ifdef MORPHTARGETS
-	uniform float morphTargetInfluences[MORPHTARGETS];
-	#include <morphtarget_vertex_declaration2> [MORPHTARGETS]
-#endif
-`
-
-const include_morphtarget_vertex_declaration2_source = `	in vec3 MorphPosition{i};
-  #ifdef MORPHTARGETS_NORMAL
-	in vec3 MorphNormal{i};
-  #endif
-`
-
 const include_phong_model_source = `/***
  phong lighting model
  Parameters:
@@ -281,176 +179,206 @@ void phongModel(vec4 position, vec3 normal, vec3 camDir, vec3 matAmbient, vec3 m
 }
 `
 
-const basic_fragment_source = `precision highp float;
+const include_attributes_source = `//
+// Vertex attributes
+//
+layout(location = 0) in  vec3  VertexPosition;
+layout(location = 1) in  vec3  VertexNormal;
+layout(location = 2) in  vec3  VertexColor;
+layout(location = 3) in  vec2  VertexTexcoord;
+`
 
-in vec3 Color;
-out vec4 FragColor;
+const include_material_source = `//
+// Material properties uniform
+//
 
-void main() {
+// Material parameters uniform array
+uniform vec3 Material[6];
+// Macros to access elements inside the Material array
+#define MatAmbientColor		Material[0]
+#define MatDiffuseColor     Material[1]
+#define MatSpecularColor    Material[2]
+#define MatEmissiveColor    Material[3]
+#define MatShininess        Material[4].x
+#define MatOpacity          Material[4].y
+#define MatPointSize        Material[4].z
+#define MatPointRotationZ   Material[5].x
 
-    FragColor = vec4(Color, 1.0);
-}
+#if MAT_TEXTURES > 0
+    // Texture unit sampler array
+    uniform sampler2D MatTexture[MAT_TEXTURES];
+    // Texture parameters (3*vec2 per texture)
+    uniform vec2 MatTexinfo[3*MAT_TEXTURES];
+    // Macros to access elements inside the MatTexinfo array
+    #define MatTexOffset(a)		MatTexinfo[(3*a)]
+    #define MatTexRepeat(a)		MatTexinfo[(3*a)+1]
+    #define MatTexFlipY(a)		bool(MatTexinfo[(3*a)+2].x)
+    #define MatTexVisible(a)	bool(MatTexinfo[(3*a)+2].y)
+    // Alpha compositing (see here: https://ciechanow.ski/alpha-compositing/)
+    vec4 Blend(vec4 texMixed, vec4 texColor) {
+        texMixed.rgb *= texMixed.a;
+        texColor.rgb *= texColor.a;
+        texMixed = texColor + texMixed * (1 - texColor.a);
+        if (texMixed.a > 0.0) {
+            texMixed.rgb /= texMixed.a;
+        }
+        return texMixed;
+    }
+#endif
 `
 
-const basic_vertex_source = `#include <attributes>
+const include_lights_source = `//
+// Lights uniforms
+//
 
-// Model uniforms
-uniform mat4 MVP;
+#if AMB_LIGHTS>0
+    // Ambient lights color uniform
+    uniform vec3 AmbientLightColor[AMB_LIGHTS];
+#endif
 
-// Final output color for fragment shader
-out vec3 Color;
+#if DIR_LIGHTS>0
+    // Directional lights uniform array. Each directional light uses 2 elements
+    uniform vec3 DirLight[2*DIR_LIGHTS];
+    // Macros to access elements inside the DirectionalLight uniform array
+    #define DirLightColor(a)		DirLight[2*a]
+    #define DirLightPosition(a)		DirLight[2*a+1]
+#endif
 
-void main() {
+#if POINT_LIGHTS>0
+    // Point lights uniform array. Each point light uses 3 elements
+    uniform vec3 PointLight[3*POINT_LIGHTS];
+    // Macros to access elements inside the PointLight uniform array
+    #define PointLightColor(a)			PointLight[3*a]
+    #define PointLightPosition(a)		PointLight[3*a+1]
+    #define PointLightLinearDecay(a)	PointLight[3*a+2].x
+    #define PointLightQuadraticDecay(a)	PointLight[3*a+2].y
+#endif
 
-    Color = VertexColor;
-    gl_Position = MVP * vec4(VertexPosition, 1.0);
-}
+#if SPOT_LIGHTS>0
+    // Spot lights uniforms. Each spot light uses 5 elements
+    uniform vec3  SpotLight[5*SPOT_LIGHTS];
+    // Macros to access elements inside the PointLight uniform array
+    #define SpotLightColor(a)			SpotLight[5*a]
+    #define SpotLightPosition(a)		SpotLight[5*a+1]
+    #define SpotLightDirection(a)		SpotLight[5*a+2]
+    #define SpotLightAngularDecay(a)	SpotLight[5*a+3].x
+    #define SpotLightCutoffAngle(a)		SpotLight[5*a+3].y
+    #define SpotLightLinearDecay(a)		SpotLight[5*a+3].z
+    #define SpotLightQuadraticDecay(a)	SpotLight[5*a+4].x
+#endif
 `
 
-const panel_fragment_source = `precision highp float;
+const include_bones_vertex_declaration_source = `#ifdef BONE_INFLUENCERS
+    #if BONE_INFLUENCERS > 0
+	uniform mat4 mBones[TOTAL_BONES];
+    in vec4 matricesIndices;
+    in vec4 matricesWeights;
+//    #if BONE_INFLUENCERS > 4
+//        in vec4 matricesIndicesExtra;
+//        in vec4 matricesWeightsExtra;
+//    #endif
+    #endif
+#endif
+`
 
-// Texture uniforms
-uniform sampler2D	MatTexture;
-uniform vec2		MatTexinfo[3];
+const point_fragment_source = `precision highp float;
 
-// Macros to access elements inside the MatTexinfo array
-#define MatTexOffset		MatTexinfo[0]
-#define MatTexRepeat		MatTexinfo[1]
-#define MatTexFlipY	    	bool(MatTexinfo[2].x) // not used
-#define MatTexVisible	    bool(MatTexinfo[2].y) // not used
+#include <material>
 
 // Inputs from vertex shader
-in vec2 FragTexcoord;
-
-// Input uniform
-uniform vec4 Panel[8];
-#define Bounds			Panel[0]		  // panel bounds in texture coordinates
-#define Border			Panel[1]		  // panel border in texture coordinates
-#define Padding			Panel[2]		  // panel padding in texture coordinates
-#define Content			Panel[3]		  // panel content area in texture coordinates
-#define BorderColor		Panel[4]		  // panel border color
-#define PaddingColor	Panel[5]		  // panel padding color
-#define ContentColor	Panel[6]		  // panel content color
-#define TextureValid	bool(Panel[7].x)  // texture valid flag
+in vec3 Color;
+flat in mat2 Rotation;
 
 // Output
 out vec4 FragColor;
 
-
-/***
-* Checks if current fragment texture coordinate is inside the
-* supplied rectangle in texture coordinates:
-* rect[0] - position x [0,1]
-* rect[1] - position y [0,1]
-* rect[2] - width [0,1]
-* rect[3] - height [0,1]
-*/
-bool checkRect(vec4 rect) {
-
-    if (FragTexcoord.x < rect[0]) {
-        return false;
-    }
-    if (FragTexcoord.x > rect[0] + rect[2]) {
-        return false;
-    }
-    if (FragTexcoord.y < rect[1]) {
-        return false;
-    }
-    if (FragTexcoord.y > rect[1] + rect[3]) {
-        return false;
-    }
-    return true;
-}
-
-
 void main() {
 
-    // Discard fragment outside of received bounds
-    // Bounds[0] - xmin
-    // Bounds[1] - ymin
-    // Bounds[2] - xmax
-    // Bounds[3] - ymax
-    if (FragTexcoord.x <= Bounds[0] || FragTexcoord.x >= Bounds[2]) {
-        discard;
-    }
-    if (FragTexcoord.y <= Bounds[1] || FragTexcoord.y >= Bounds[3]) {
-        discard;
-    }
-
-    // Check if fragment is inside content area
-    if (checkRect(Content)) {
-
-        // If no texture, the color will be the material color.
-        vec4 color = ContentColor;
-
-		if (TextureValid) {
-            // Adjust texture coordinates to fit texture inside the content area
-            vec2 offset = vec2(-Content[0], -Content[1]);
-            vec2 factor = vec2(1.0/Content[2], 1.0/Content[3]);
-            vec2 texcoord = (FragTexcoord + offset) * factor;
-            vec4 texColor = texture(MatTexture, texcoord * MatTexRepeat + MatTexOffset);
-
-            // Mix content color with texture color.
-            // Note that doing a simple linear interpolation (e.g. using mix()) is not correct!
-            // The right formula can be found here: https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
-            // For a more in-depth discussion: http://apoorvaj.io/alpha-compositing-opengl-blending-and-premultiplied-alpha.html#toc4
-            // Another great discussion here: https://ciechanow.ski/alpha-compositing/
-
-            // Alpha premultiply the content color
-            vec4 contentPre = ContentColor;
-            contentPre.rgb *= contentPre.a;
-
-            // Alpha premultiply the content color
-            vec4 texPre = texColor;
-            texPre.rgb *= texPre.a;
+    // Compute final texture color
+    vec4 texMixed = vec4(1);
+    #if MAT_TEXTURES > 0
+        vec2 pointCoord = Rotation * gl_PointCoord - vec2(0.5) + vec2(0.5);
+        bool firstTex = true;
+        if (MatTexVisible(0)) {
+            vec4 texColor = texture(MatTexture[0], pointCoord * MatTexRepeat(0) + MatTexOffset(0));
+            if (firstTex) {
+                texMixed = texColor;
+                firstTex = false;
+            } else {
+                texMixed = Blend(texMixed, texColor);
+            }
+        }
+        #if MAT_TEXTURES > 1
+            if (MatTexVisible(1)) {
+                vec4 texColor = texture(MatTexture[1], pointCoord * MatTexRepeat(1) + MatTexOffset(1));
+                if (firstTex) {
+                    texMixed = texColor;
+                    firstTex = false;
+                } else {
+                    texMixed = Blend(texMixed, texColor);
+                }
+            }
+            #if MAT_TEXTURES > 2
+                if (MatTexVisible(2)) {
+                    vec4 texColor = texture(MatTexture[2], pointCoord * MatTexRepeat(2) + MatTexOffset(2));
+                    if (firstTex) {
+                        texMixed = texColor;
+                        firstTex = false;
+                    } else {
+                        texMixed = Blend(texMixed, texColor);
+                    }
+                }
+            #endif
+        #endif
+    #endif
 
-            // Combine colors to obtain the alpha premultiplied final color
-            color = texPre + contentPre * (1.0 - texPre.a);
+    // Generates final color
+    FragColor = min(vec4(Color, MatOpacity) * texMixed, vec4(1));
+}
+`
 
-            // Un-alpha-premultiply
-            color.rgb /= color.a;
-		}
+const physical_vertex_source = `//
+// Physically Based Shading of a microfacet surface material - Vertex Shader
+// Modified from reference implementation at https://github.com/KhronosGroup/glTF-WebGL-PBR
+//
+#include <attributes>
 
-        FragColor = color;
-        return;
-    }
+// Model uniforms
+uniform mat4 ModelViewMatrix;
+uniform mat3 NormalMatrix;
+uniform mat4 MVP;
 
-    // Checks if fragment is inside paddings area
-    if (checkRect(Padding)) {
-        FragColor = PaddingColor;
-        return;
-    }
+#include <morphtarget_vertex_declaration>
+#include <bones_vertex_declaration>
 
-    // Checks if fragment is inside borders area
-    if (checkRect(Border)) {
-        FragColor = BorderColor;
-        return;
-    }
+// Output variables for Fragment shader
+out vec3 Position;
+out vec3 Normal;
+out vec3 CamDir;
+out vec2 FragTexcoord;
 
-    // Fragment is in margins area (always transparent)
-    FragColor = vec4(1,1,1,0);
-}
-`
+void main() {
 
-const panel_vertex_source = `#include <attributes>
+    // Transform this vertex position to camera coordinates.
+    Position = vec3(ModelViewMatrix * vec4(VertexPosition, 1.0));
 
-// Model uniforms
-uniform mat4 ModelMatrix;
+    // Transform this vertex normal to camera coordinates.
+    Normal = normalize(NormalMatrix * VertexNormal);
 
-// Outputs for fragment shader
-out vec2 FragTexcoord;
+    // Calculate the direction vector from the vertex to the camera
+    // The camera is at 0,0,0
+    CamDir = normalize(-Position.xyz);
 
+    // Output texture coordinates to fragment shader
+    FragTexcoord = VertexTexcoord;
 
-void main() {
+    vec3 vPosition = VertexPosition;
+    mat4 finalWorld = mat4(1.0);
+    #include <morphtarget_vertex>
+    #include <bones_vertex>
 
-    // Always flip texture coordinates
-    vec2 texcoord = VertexTexcoord;
-    texcoord.y = 1.0 - texcoord.y;
-    FragTexcoord = texcoord;
+    gl_Position = MVP * finalWorld * vec4(vPosition, 1.0);
 
-    // Set position
-    vec4 pos = vec4(VertexPosition.xyz, 1);
-    gl_Position = ModelMatrix * pos;
 }
 `
 
@@ -869,139 +797,95 @@ void main() {
 }
 `
 
-const physical_vertex_source = `//
-// Physically Based Shading of a microfacet surface material - Vertex Shader
-// Modified from reference implementation at https://github.com/KhronosGroup/glTF-WebGL-PBR
-//
-#include <attributes>
+const point_vertex_source = `#include <attributes>
+
+// Model uniforms
+uniform mat4 MVP;
+uniform mat4 MV;
+
+// Material uniforms
+#include <material>
+
+// Outputs for fragment shader
+out vec3 Color;
+flat out mat2 Rotation;
+
+void main() {
+
+    // Rotation matrix for fragment shader
+    float rotSin = sin(MatPointRotationZ);
+    float rotCos = cos(MatPointRotationZ);
+    Rotation = mat2(rotCos, rotSin, - rotSin, rotCos);
+
+    // Sets the vertex position
+    vec4 pos = MVP * vec4(VertexPosition, 1.0);
+    gl_Position = pos;
+
+    // Sets the size of the rasterized point decreasing with distance
+    vec4 posMV = MV * vec4(VertexPosition, 1.0);
+    gl_PointSize = MatPointSize / -posMV.z;
+
+    // Outputs color
+    Color = MatEmissiveColor;
+}
+
+`
+
+const standard_vertex_source = `#include <attributes>
 
 // Model uniforms
 uniform mat4 ModelViewMatrix;
 uniform mat3 NormalMatrix;
 uniform mat4 MVP;
 
+#include <material>
 #include <morphtarget_vertex_declaration>
 #include <bones_vertex_declaration>
 
 // Output variables for Fragment shader
-out vec3 Position;
+out vec4 Position;
 out vec3 Normal;
-out vec3 CamDir;
 out vec2 FragTexcoord;
 
 void main() {
 
-    // Transform this vertex position to camera coordinates.
-    Position = vec3(ModelViewMatrix * vec4(VertexPosition, 1.0));
+    // Transform vertex position to camera coordinates
+    Position = ModelViewMatrix * vec4(VertexPosition, 1.0);
 
-    // Transform this vertex normal to camera coordinates.
+    // Transform vertex normal to camera coordinates
     Normal = normalize(NormalMatrix * VertexNormal);
 
-    // Calculate the direction vector from the vertex to the camera
-    // The camera is at 0,0,0
-    CamDir = normalize(-Position.xyz);
-
-    // Output texture coordinates to fragment shader
-    FragTexcoord = VertexTexcoord;
-
-    vec3 vPosition = VertexPosition;
-    mat4 finalWorld = mat4(1.0);
-    #include <morphtarget_vertex>
-    #include <bones_vertex>
-
-    gl_Position = MVP * finalWorld * vec4(vPosition, 1.0);
-
-}
-`
-
-const point_fragment_source = `precision highp float;
-
-#include <material>
-
-// Inputs from vertex shader
-in vec3 Color;
-flat in mat2 Rotation;
-
-// Output
-out vec4 FragColor;
-
-void main() {
-
-    // Compute final texture color
-    vec4 texMixed = vec4(1);
-    #if MAT_TEXTURES > 0
-        vec2 pointCoord = Rotation * gl_PointCoord - vec2(0.5) + vec2(0.5);
-        bool firstTex = true;
-        if (MatTexVisible(0)) {
-            vec4 texColor = texture(MatTexture[0], pointCoord * MatTexRepeat(0) + MatTexOffset(0));
-            if (firstTex) {
-                texMixed = texColor;
-                firstTex = false;
-            } else {
-                texMixed = Blend(texMixed, texColor);
-            }
-        }
-        #if MAT_TEXTURES > 1
-            if (MatTexVisible(1)) {
-                vec4 texColor = texture(MatTexture[1], pointCoord * MatTexRepeat(1) + MatTexOffset(1));
-                if (firstTex) {
-                    texMixed = texColor;
-                    firstTex = false;
-                } else {
-                    texMixed = Blend(texMixed, texColor);
-                }
-            }
-            #if MAT_TEXTURES > 2
-                if (MatTexVisible(2)) {
-                    vec4 texColor = texture(MatTexture[2], pointCoord * MatTexRepeat(2) + MatTexOffset(2));
-                    if (firstTex) {
-                        texMixed = texColor;
-                        firstTex = false;
-                    } else {
-                        texMixed = Blend(texMixed, texColor);
-                    }
-                }
-            #endif
-        #endif
-    #endif
+    vec2 texcoord = VertexTexcoord;
+#if MAT_TEXTURES > 0
+    // Flip texture coordinate Y if requested.
+    if (MatTexFlipY(0)) {
+        texcoord.y = 1.0 - texcoord.y;
+    }
+#endif
+    FragTexcoord = texcoord;
+    vec3 vPosition = VertexPosition;
+    mat4 finalWorld = mat4(1.0);
+    #include <morphtarget_vertex>
+    #include <bones_vertex>
 
-    // Generates final color
-    FragColor = min(vec4(Color, MatOpacity) * texMixed, vec4(1));
+    // Output projected and transformed vertex position
+    gl_Position = MVP * finalWorld * vec4(vPosition, 1.0);
 }
 `
 
-const point_vertex_source = `#include <attributes>
+const basic_vertex_source = `#include <attributes>
 
 // Model uniforms
 uniform mat4 MVP;
-uniform mat4 MV;
-
-// Material uniforms
-#include <material>
 
-// Outputs for fragment shader
+// Final output color for fragment shader
 out vec3 Color;
-flat out mat2 Rotation;
 
 void main() {
 
-    // Rotation matrix for fragment shader
-    float rotSin = sin(MatPointRotationZ);
-    float rotCos = cos(MatPointRotationZ);
-    Rotation = mat2(rotCos, rotSin, - rotSin, rotCos);
-
-    // Sets the vertex position
-    vec4 pos = MVP * vec4(VertexPosition, 1.0);
-    gl_Position = pos;
-
-    // Sets the size of the rasterized point decreasing with distance
-    vec4 posMV = MV * vec4(VertexPosition, 1.0);
-    gl_PointSize = MatPointSize / -posMV.z;
-
-    // Outputs color
-    Color = MatEmissiveColor;
+    Color = VertexColor;
+    gl_Position = MVP * vec4(VertexPosition, 1.0);
 }
-
 `
 
 const standard_fragment_source = `precision highp float;
@@ -1084,76 +968,192 @@ void main() {
 }
 `
 
-const standard_vertex_source = `#include <attributes>
+const panel_vertex_source = `#include <attributes>
 
 // Model uniforms
-uniform mat4 ModelViewMatrix;
-uniform mat3 NormalMatrix;
-uniform mat4 MVP;
-
-#include <material>
-#include <morphtarget_vertex_declaration>
-#include <bones_vertex_declaration>
+uniform mat4 ModelMatrix;
 
-// Output variables for Fragment shader
-out vec4 Position;
-out vec3 Normal;
+// Outputs for fragment shader
 out vec2 FragTexcoord;
 
+
 void main() {
 
-    // Transform vertex position to camera coordinates
-    Position = ModelViewMatrix * vec4(VertexPosition, 1.0);
+    // Always flip texture coordinates
+    vec2 texcoord = VertexTexcoord;
+    texcoord.y = 1.0 - texcoord.y;
+    FragTexcoord = texcoord;
 
-    // Transform vertex normal to camera coordinates
-    Normal = normalize(NormalMatrix * VertexNormal);
+    // Set position
+    vec4 pos = vec4(VertexPosition.xyz, 1);
+    gl_Position = ModelMatrix * pos;
+}
+`
 
-    vec2 texcoord = VertexTexcoord;
-#if MAT_TEXTURES > 0
-    // Flip texture coordinate Y if requested.
-    if (MatTexFlipY(0)) {
-        texcoord.y = 1.0 - texcoord.y;
+const basic_fragment_source = `precision highp float;
+
+in vec3 Color;
+out vec4 FragColor;
+
+void main() {
+
+    FragColor = vec4(Color, 1.0);
+}
+`
+
+const panel_fragment_source = `precision highp float;
+
+// Texture uniforms
+uniform sampler2D	MatTexture;
+uniform vec2		MatTexinfo[3];
+
+// Macros to access elements inside the MatTexinfo array
+#define MatTexOffset		MatTexinfo[0]
+#define MatTexRepeat		MatTexinfo[1]
+#define MatTexFlipY	    	bool(MatTexinfo[2].x) // not used
+#define MatTexVisible	    bool(MatTexinfo[2].y) // not used
+
+// Inputs from vertex shader
+in vec2 FragTexcoord;
+
+// Input uniform
+uniform vec4 Panel[8];
+#define Bounds			Panel[0]		  // panel bounds in texture coordinates
+#define Border			Panel[1]		  // panel border in texture coordinates
+#define Padding			Panel[2]		  // panel padding in texture coordinates
+#define Content			Panel[3]		  // panel content area in texture coordinates
+#define BorderColor		Panel[4]		  // panel border color
+#define PaddingColor	Panel[5]		  // panel padding color
+#define ContentColor	Panel[6]		  // panel content color
+#define TextureValid	bool(Panel[7].x)  // texture valid flag
+
+// Output
+out vec4 FragColor;
+
+
+/***
+* Checks if current fragment texture coordinate is inside the
+* supplied rectangle in texture coordinates:
+* rect[0] - position x [0,1]
+* rect[1] - position y [0,1]
+* rect[2] - width [0,1]
+* rect[3] - height [0,1]
+*/
+bool checkRect(vec4 rect) {
+
+    if (FragTexcoord.x < rect[0]) {
+        return false;
     }
-#endif
-    FragTexcoord = texcoord;
-    vec3 vPosition = VertexPosition;
-    mat4 finalWorld = mat4(1.0);
-    #include <morphtarget_vertex>
-    #include <bones_vertex>
+    if (FragTexcoord.x > rect[0] + rect[2]) {
+        return false;
+    }
+    if (FragTexcoord.y < rect[1]) {
+        return false;
+    }
+    if (FragTexcoord.y > rect[1] + rect[3]) {
+        return false;
+    }
+    return true;
+}
 
-    // Output projected and transformed vertex position
-    gl_Position = MVP * finalWorld * vec4(vPosition, 1.0);
+
+void main() {
+
+    // Discard fragment outside of received bounds
+    // Bounds[0] - xmin
+    // Bounds[1] - ymin
+    // Bounds[2] - xmax
+    // Bounds[3] - ymax
+    if (FragTexcoord.x <= Bounds[0] || FragTexcoord.x >= Bounds[2]) {
+        discard;
+    }
+    if (FragTexcoord.y <= Bounds[1] || FragTexcoord.y >= Bounds[3]) {
+        discard;
+    }
+
+    // Check if fragment is inside content area
+    if (checkRect(Content)) {
+
+        // If no texture, the color will be the material color.
+        vec4 color = ContentColor;
+
+		if (TextureValid) {
+            // Adjust texture coordinates to fit texture inside the content area
+            vec2 offset = vec2(-Content[0], -Content[1]);
+            vec2 factor = vec2(1.0/Content[2], 1.0/Content[3]);
+            vec2 texcoord = (FragTexcoord + offset) * factor;
+            vec4 texColor = texture(MatTexture, texcoord * MatTexRepeat + MatTexOffset);
+
+            // Mix content color with texture color.
+            // Note that doing a simple linear interpolation (e.g. using mix()) is not correct!
+            // The right formula can be found here: https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
+            // For a more in-depth discussion: http://apoorvaj.io/alpha-compositing-opengl-blending-and-premultiplied-alpha.html#toc4
+            // Another great discussion here: https://ciechanow.ski/alpha-compositing/
+
+            // Alpha premultiply the content color
+            vec4 contentPre = ContentColor;
+            contentPre.rgb *= contentPre.a;
+
+            // Alpha premultiply the content color
+            vec4 texPre = texColor;
+            texPre.rgb *= texPre.a;
+
+            // Combine colors to obtain the alpha premultiplied final color
+            color = texPre + contentPre * (1.0 - texPre.a);
+
+            // Un-alpha-premultiply
+            color.rgb /= color.a;
+		}
+
+        FragColor = color;
+        return;
+    }
+
+    // Checks if fragment is inside paddings area
+    if (checkRect(Padding)) {
+        FragColor = PaddingColor;
+        return;
+    }
+
+    // Checks if fragment is inside borders area
+    if (checkRect(Border)) {
+        FragColor = BorderColor;
+        return;
+    }
+
+    // Fragment is in margins area (always transparent)
+    FragColor = vec4(1,1,1,0);
 }
 `
 
 // Maps include name with its source code
 var includeMap = map[string]string{
 
-	"attributes":                      include_attributes_source,
-	"bones_vertex":                    include_bones_vertex_source,
-	"bones_vertex_declaration":        include_bones_vertex_declaration_source,
-	"lights":                          include_lights_source,
-	"material":                        include_material_source,
-	"morphtarget_vertex":              include_morphtarget_vertex_source,
 	"morphtarget_vertex2":             include_morphtarget_vertex2_source,
-	"morphtarget_vertex_declaration":  include_morphtarget_vertex_declaration_source,
 	"morphtarget_vertex_declaration2": include_morphtarget_vertex_declaration2_source,
+	"morphtarget_vertex":              include_morphtarget_vertex_source,
+	"morphtarget_vertex_declaration":  include_morphtarget_vertex_declaration_source,
+	"bones_vertex":                    include_bones_vertex_source,
 	"phong_model":                     include_phong_model_source,
+	"attributes":                      include_attributes_source,
+	"material":                        include_material_source,
+	"lights":                          include_lights_source,
+	"bones_vertex_declaration":        include_bones_vertex_declaration_source,
 }
 
 // Maps shader name with its source code
 var shaderMap = map[string]string{
 
-	"basic_fragment":    basic_fragment_source,
-	"basic_vertex":      basic_vertex_source,
-	"panel_fragment":    panel_fragment_source,
-	"panel_vertex":      panel_vertex_source,
-	"physical_fragment": physical_fragment_source,
-	"physical_vertex":   physical_vertex_source,
 	"point_fragment":    point_fragment_source,
+	"physical_vertex":   physical_vertex_source,
+	"physical_fragment": physical_fragment_source,
 	"point_vertex":      point_vertex_source,
-	"standard_fragment": standard_fragment_source,
 	"standard_vertex":   standard_vertex_source,
+	"basic_vertex":      basic_vertex_source,
+	"standard_fragment": standard_fragment_source,
+	"panel_vertex":      panel_vertex_source,
+	"basic_fragment":    basic_fragment_source,
+	"panel_fragment":    panel_fragment_source,
 }
 
 // Maps program name with Proginfo struct with shaders names

+ 1 - 0
renderer/version-browser.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build wasm
 // +build wasm
 
 package renderer

+ 1 - 0
renderer/version-desktop.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !wasm
 // +build !wasm
 
 package renderer

+ 2 - 2
util/wasm/wasm.go

@@ -1,5 +1,5 @@
-// +build wasm
-// +build go1.13
+//go:build wasm && go1.13
+// +build wasm,go1.13
 
 package wasm
 

+ 3 - 2
window/canvas.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build wasm
 // +build wasm
 
 package window
@@ -267,7 +268,7 @@ var keyMap = map[string]Key{
 	"ControlLeft":  KeyLeftControl,
 	"AltLeft":      KeyLeftAlt,
 	"MetaLeft":     KeyLeftSuper,
-	"ShitRight":    KeyRightShift,
+	"ShiftRight":   KeyRightShift,
 	"ControlRight": KeyRightControl,
 	"AltRight":     KeyRightAlt,
 	"MetaRight":    KeyRightSuper,
@@ -338,7 +339,7 @@ type WebGlCanvas struct {
 	mouseWheel js.Func
 	winResize  js.Func
 	winFocus   js.Func
-	winBlur   js.Func
+	winBlur    js.Func
 }
 
 // Init initializes the WebGlCanvas singleton.

+ 1 - 0
window/glfw.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !wasm
 // +build !wasm
 
 package window