Skip to content

RendererException while rendering old animation with hardware skinning disabled #2571

@stephengold

Description

@stephengold

I discovered this issue while trying to load OtoOldAnim.j3o from jme3-testdata into my DacWizard application.

A simple way to reproduce it is to modify "TestHWSkinningOld.java" so that hwSkinningEnable defaults to false:

--- a/jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinningOld.java
+++ b/jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinningOld.java
@@ -48,7 +48,7 @@
 
     final private String[] animNames = {"Dodge", "Walk", "pull", "push"};
     private final static int SIZE = 50;
-    private boolean hwSkinningEnable = true;
\ No newline at end of file
+    private boolean hwSkinningEnable = false;
\ No newline at end of file
     final private List<SkeletonControl> skControls = new ArrayList<>();
     private BitmapText hwsText;

When the modified TestHWSkinningOld app is run, it crashes with the following console output:

> Configure project :
Latest tag:v3.9.0-alpha5
Auto-detecting version
Revision: 8661
Hash: 827aa3e99cf08ad88f2150d7882398c93513ac3d
Short Hash: 827aa3e
Tag: null
Build Date: 2025-12-07
Build Branch: master
Use commit hash as version false
Base Version: 3.9.0
Build Suffix: SNAPSHOT
Build Version: 3.9.0-SNAPSHOT
Use natives snapshot: https://objects.jmonkeyengine.org/native-snapshots/c67259e3689cd8531761d189a0dc2ba86c95c767/jme3-natives.zip

> Task :jme3-core:compileJava UP-TO-DATE
> Task :jme3-core:compileGroovy NO-SOURCE
> Task :jme3-core:updateVersionPropertiesFile UP-TO-DATE
> Task :jme3-core:processResources UP-TO-DATE
> Task :jme3-core:classes UP-TO-DATE
> Task :jme3-core:jar UP-TO-DATE
> Task :jme3-awt-dialogs:compileJava UP-TO-DATE
> Task :jme3-awt-dialogs:compileGroovy NO-SOURCE
> Task :jme3-awt-dialogs:processResources NO-SOURCE
> Task :jme3-awt-dialogs:classes UP-TO-DATE
> Task :jme3-awt-dialogs:jar UP-TO-DATE
> Task :jme3-desktop:compileJava UP-TO-DATE
> Task :jme3-desktop:compileGroovy NO-SOURCE
> Task :jme3-desktop:processResources UP-TO-DATE
> Task :jme3-desktop:classes UP-TO-DATE
> Task :jme3-desktop:jar UP-TO-DATE
> Task :jme3-effects:compileJava UP-TO-DATE
> Task :jme3-effects:compileGroovy NO-SOURCE
> Task :jme3-effects:processResources UP-TO-DATE
> Task :jme3-effects:classes UP-TO-DATE
> Task :jme3-effects:jar UP-TO-DATE
> Task :jme3-lwjgl3:compileJava UP-TO-DATE
> Task :jme3-lwjgl3:compileGroovy NO-SOURCE
> Task :jme3-lwjgl3:processResources NO-SOURCE
> Task :jme3-lwjgl3:classes UP-TO-DATE
> Task :jme3-lwjgl3:jar UP-TO-DATE
> Task :jme3-terrain:compileJava UP-TO-DATE
> Task :jme3-terrain:compileGroovy NO-SOURCE
> Task :jme3-terrain:processResources UP-TO-DATE
> Task :jme3-terrain:classes UP-TO-DATE
> Task :jme3-terrain:jar UP-TO-DATE
> Task :jme3-vr:compileJava UP-TO-DATE
> Task :jme3-vr:compileGroovy NO-SOURCE
> Task :jme3-vr:processResources UP-TO-DATE
> Task :jme3-vr:classes UP-TO-DATE
> Task :jme3-vr:jar UP-TO-DATE
> Task :jme3-jbullet:compileJava UP-TO-DATE
> Task :jme3-jbullet:compileGroovy NO-SOURCE
> Task :jme3-jbullet:processResources NO-SOURCE
> Task :jme3-jbullet:classes UP-TO-DATE
> Task :jme3-jbullet:jar UP-TO-DATE
> Task :jme3-jogg:compileJava UP-TO-DATE
> Task :jme3-jogg:compileGroovy NO-SOURCE
> Task :jme3-jogg:processResources NO-SOURCE
> Task :jme3-jogg:classes UP-TO-DATE
> Task :jme3-jogg:jar UP-TO-DATE
> Task :jme3-lwjgl:compileJava UP-TO-DATE
> Task :jme3-lwjgl:compileGroovy NO-SOURCE
> Task :jme3-lwjgl:processResources NO-SOURCE
> Task :jme3-lwjgl:classes UP-TO-DATE
> Task :jme3-lwjgl:jar UP-TO-DATE
> Task :jme3-networking:compileJava UP-TO-DATE
> Task :jme3-networking:compileGroovy NO-SOURCE
> Task :jme3-networking:processResources NO-SOURCE
> Task :jme3-networking:classes UP-TO-DATE
> Task :jme3-networking:jar UP-TO-DATE
> Task :jme3-niftygui:compileJava UP-TO-DATE
> Task :jme3-niftygui:compileGroovy NO-SOURCE
> Task :jme3-niftygui:processResources UP-TO-DATE
> Task :jme3-niftygui:classes UP-TO-DATE
> Task :jme3-niftygui:jar UP-TO-DATE
> Task :jme3-plugins-json:compileJava UP-TO-DATE
> Task :jme3-plugins-json:compileGroovy NO-SOURCE
> Task :jme3-plugins-json:processResources NO-SOURCE
> Task :jme3-plugins-json:classes UP-TO-DATE
> Task :jme3-plugins-json:jar UP-TO-DATE
> Task :jme3-plugins-json-gson:compileJava UP-TO-DATE
> Task :jme3-plugins-json-gson:compileGroovy NO-SOURCE
> Task :jme3-plugins-json-gson:processResources NO-SOURCE
> Task :jme3-plugins-json-gson:classes UP-TO-DATE
> Task :jme3-plugins-json-gson:jar UP-TO-DATE
> Task :jme3-plugins:compileJava UP-TO-DATE
> Task :jme3-plugins:compileGroovy NO-SOURCE
> Task :jme3-plugins:processResources NO-SOURCE
> Task :jme3-plugins:classes UP-TO-DATE
> Task :jme3-plugins:jar UP-TO-DATE
> Task :jme3-examples:compileJava UP-TO-DATE
> Task :jme3-examples:compileGroovy NO-SOURCE
> Task :jme3-examples:processResources UP-TO-DATE
> Task :jme3-examples:classes UP-TO-DATE
> Task :jme3-examples:jar UP-TO-DATE
> Task :jme3-examples:javadoc UP-TO-DATE
> Task :jme3-examples:javadocJar UP-TO-DATE
> Task :jme3-examples:sourcesJar UP-TO-DATE
> Task :jme3-examples:signArchives SKIPPED
> Task :jme3-examples:assemble UP-TO-DATE
> Task :jme3-examples:checkstyleMain NO-SOURCE
> Task :jme3-examples:compileTestJava NO-SOURCE
> Task :jme3-examples:compileTestGroovy NO-SOURCE
> Task :jme3-examples:processTestResources NO-SOURCE
> Task :jme3-examples:testClasses UP-TO-DATE
> Task :jme3-examples:checkstyleTest NO-SOURCE
> Task :jme3-testdata:compileJava NO-SOURCE
> Task :jme3-testdata:compileGroovy NO-SOURCE
> Task :jme3-testdata:processResources UP-TO-DATE
> Task :jme3-testdata:classes UP-TO-DATE
> Task :jme3-testdata:jar UP-TO-DATE
> Task :jme3-examples:test NO-SOURCE
> Task :jme3-examples:check UP-TO-DATE
> Task :jme3-examples:build UP-TO-DATE

> Task :jme3-examples:run
Dec 07, 2025 11:51:18 AM com.jme3.awt.AWTSettingsDialog <init>
INFO: Loading AppSettings from PreferenceKey: jMonkeyEngine 3.9.0-SNAPSHOT
Dec 07, 2025 11:51:18 AM com.jme3.system.AppSettings printPreferences
INFO: Preferences for key: jMonkeyEngine 3.9.0-SNAPSHOT
 * B_CenterWindow = true
 * B_DisableJoysticks = true
 * B_Fullscreen = false
 * B_GammaCorrection = true
 * B_OpenCL = false
 * B_Resizable = false
 * B_SwapBuffers = true
 * B_UseInput = true
 * B_UseRetinaFrameBuffer = false
 * B_VSync = true
 * B_X11PlatformPreferred = false
 * I_BitsPerPixel = 24
 * I_DepthBits = 24
 * I_Display = 0
 * I_FrameRate = -1
 * I_Frequency = -1
 * I_Height = 480
 * I_MinHeight = 0
 * I_MinWidth = 0
 * I_Samples = 0
 * I_StencilBits = 0
 * I_Width = 640
 * I_WindowHeight = -2147483648
 * I_WindowWidth = -2147483648
 * I_WindowXPosition = 0
 * I_WindowYPosition = 0
 * S_AudioRenderer = LWJGL
 * S_OpenCLPlatformChooser = com.jme3.opencl.DefaultPlatformChooser
 * S_Renderer = LWJGL-OpenGL3
 * S_SettingsDialogImage = /com/jme3/app/Monkey.png
 * S_Title = jMonkeyEngine 3.9.0-SNAPSHOT
Dec 07, 2025 11:51:21 AM com.jme3.awt.AWTSettingsDialog verifyAndSaveCurrentSelection
INFO: Saving AppSettings to PreferencesKey: jMonkeyEngine 3.9.0-SNAPSHOT
Dec 07, 2025 11:51:21 AM com.jme3.system.AppSettings printPreferences
INFO: Preferences for key: jMonkeyEngine 3.9.0-SNAPSHOT
 * B_CenterWindow = true
 * B_DisableJoysticks = true
 * B_Fullscreen = false
 * B_GammaCorrection = true
 * B_OpenCL = false
 * B_Resizable = false
 * B_SwapBuffers = true
 * B_UseInput = true
 * B_UseRetinaFrameBuffer = false
 * B_VSync = true
 * B_X11PlatformPreferred = false
 * I_BitsPerPixel = 24
 * I_DepthBits = 24
 * I_Display = 0
 * I_FrameRate = -1
 * I_Frequency = -1
 * I_Height = 480
 * I_MinHeight = 0
 * I_MinWidth = 0
 * I_Samples = 0
 * I_StencilBits = 0
 * I_Width = 640
 * I_WindowHeight = -2147483648
 * I_WindowWidth = -2147483648
 * I_WindowXPosition = 0
 * I_WindowYPosition = 0
 * S_AudioRenderer = LWJGL
 * S_OpenCLPlatformChooser = com.jme3.opencl.DefaultPlatformChooser
 * S_Renderer = LWJGL-OpenGL3
 * S_SettingsDialogImage = /com/jme3/app/Monkey.png
 * S_Title = jMonkeyEngine 3.9.0-SNAPSHOT
Dec 07, 2025 11:51:21 AM com.jme3.system.JmeDesktopSystem initialize
INFO: Running on jMonkeyEngine 3.9.0-SNAPSHOT
 * Branch: master
 * Git Hash: 827aa3e
 * Build Date: 2025-12-07
Dec 07, 2025 11:51:21 AM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: LWJGL 2.9.5 context running on thread jME3 Main
 * Graphics Adapter: null
 * Driver Version: null
 * Scaling Factor: 1
Dec 07, 2025 11:51:21 AM com.jme3.renderer.opengl.GLRenderer loadCapabilitiesCommon
INFO: OpenGL Renderer Information
 * Vendor: NVIDIA Corporation
 * Renderer: NVIDIA GeForce RTX 2070/PCIe/SSE2
 * OpenGL Version: 3.2.0 NVIDIA 580.95.05
 * GLSL Version: 1.50 NVIDIA via Cg compiler
 * Profile: Core
Dec 07, 2025 11:51:22 AM com.jme3.audio.openal.ALAudioRenderer printAudioRendererInfo
INFO: Audio Renderer Information
 * Device: OpenAL Soft
 * Vendor: OpenAL Community
 * Renderer: OpenAL Soft
 * Version: 1.1 ALSOFT 1.15.1
 * Supported channels: 64
 * ALC extensions: ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX ALC_EXT_thread_local_context ALC_SOFT_loopback
 * AL extensions: AL_EXT_ALAW AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data AL_SOFTX_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points AL_SOFT_source_latency
Dec 07, 2025 11:51:22 AM com.jme3.audio.openal.ALAudioRenderer initOpenAL
WARNING: Pausing audio device not supported (ALC_SOFT_pause_device).
Dec 07, 2025 11:51:22 AM com.jme3.audio.openal.ALAudioRenderer initEfx
INFO: Audio effect extension version: 1.0
Dec 07, 2025 11:51:22 AM com.jme3.audio.openal.ALAudioRenderer initEfx
INFO: Audio max auxiliary sends: 4
Dec 07, 2025 11:51:23 AM com.jme3.renderer.opengl.GLRenderer updateShaderSourceData
WARNING: Bad compile of:
1	#version 150 core
2	#define SRGB 1
3	#define VERTEX_SHADER 1
4	#define BOUND_DRAW_BUFFER 0
5	#define VERTEX_COLOR 1
6	#define MATERIAL_COLORS 1
7	#define DIFFUSEMAP 1
8	#define NUM_BONES 0
9	// -- begin import Common/ShaderLib/GLSLCompat.glsllib --
10	#ifdef GL_ES
11	  #ifdef FRAGMENT_SHADER
12	    precision highp float;
13	    precision highp int;
14	    #if __VERSION__ >= 130
15	      precision highp sampler2DArray;        
16	    #endif
17	    precision highp sampler2DArray;
18	    precision highp sampler2DShadow;
19	    precision highp samplerCube;
20	    precision highp sampler3D;
21	    precision highp sampler2D;
22	    #if __VERSION__ >= 310
23	      precision highp sampler2DMS;
24	    #endif
25	  #endif
26	#endif
27	
28	#if defined GL_ES
29	#  define hfloat highp float
30	#  define hvec2  highp vec2
31	#  define hvec3  highp vec3
32	#  define hvec4  highp vec4
33	#  define lfloat lowp float
34	#  define lvec2 lowp vec2
35	#  define lvec3 lowp vec3
36	#  define lvec4 lowp vec4
37	#else
38	#  define hfloat float
39	#  define hvec2  vec2
40	#  define hvec3  vec3
41	#  define hvec4  vec4
42	#  define lfloat float
43	#  define lvec2  vec2
44	#  define lvec3  vec3
45	#  define lvec4  vec4
46	#endif
47	
48	#if __VERSION__ >= 130
49	
50	#ifdef FRAGMENT_SHADER
51	  #ifdef GL_ES
52	    #ifdef BOUND_DRAW_BUFFER
53	
54	 #if 0<=BOUND_DRAW_BUFFER  
55	        #if BOUND_DRAW_BUFFER == 0
56	          layout( location = 0 ) out highp vec4 outFragColor;
57	        #else
58	          layout( location = 0 ) out highp vec4 outNOP0;
59	        #endif
60	 #endif 
61	
62	 #if 1<=BOUND_DRAW_BUFFER  
63	        #if BOUND_DRAW_BUFFER == 1
64	          layout( location = 1 ) out highp vec4 outFragColor;
65	        #else
66	          layout( location = 1 ) out highp vec4 outNOP1;
67	        #endif
68	 #endif 
69	
70	 #if 2<=BOUND_DRAW_BUFFER  
71	        #if BOUND_DRAW_BUFFER == 2
72	          layout( location = 2 ) out highp vec4 outFragColor;
73	        #else
74	          layout( location = 2 ) out highp vec4 outNOP2;
75	        #endif
76	 #endif 
77	
78	 #if 3<=BOUND_DRAW_BUFFER  
79	        #if BOUND_DRAW_BUFFER == 3
80	          layout( location = 3 ) out highp vec4 outFragColor;
81	        #else
82	          layout( location = 3 ) out highp vec4 outNOP3;
83	        #endif
84	 #endif 
85	
86	 #if 4<=BOUND_DRAW_BUFFER  
87	        #if BOUND_DRAW_BUFFER == 4
88	          layout( location = 4 ) out highp vec4 outFragColor;
89	        #else
90	          layout( location = 4 ) out highp vec4 outNOP4;
91	        #endif
92	 #endif 
93	
94	 #if 5<=BOUND_DRAW_BUFFER  
95	        #if BOUND_DRAW_BUFFER == 5
96	          layout( location = 5 ) out highp vec4 outFragColor;
97	        #else
98	          layout( location = 5 ) out highp vec4 outNOP5;
99	        #endif
100	 #endif 
101	
102	 #if 6<=BOUND_DRAW_BUFFER  
103	        #if BOUND_DRAW_BUFFER == 6
104	          layout( location = 6 ) out highp vec4 outFragColor;
105	        #else
106	          layout( location = 6 ) out highp vec4 outNOP6;
107	        #endif
108	 #endif 
109	
110	 #if 7<=BOUND_DRAW_BUFFER  
111	        #if BOUND_DRAW_BUFFER == 7
112	          layout( location = 7 ) out highp vec4 outFragColor;
113	        #else
114	          layout( location = 7 ) out highp vec4 outNOP7;
115	        #endif
116	 #endif 
117	
118	 #if 8<=BOUND_DRAW_BUFFER  
119	        #if BOUND_DRAW_BUFFER == 8
120	          layout( location = 8 ) out highp vec4 outFragColor;
121	        #else
122	          layout( location = 8 ) out highp vec4 outNOP8;
123	        #endif
124	 #endif 
125	
126	 #if 9<=BOUND_DRAW_BUFFER  
127	        #if BOUND_DRAW_BUFFER == 9
128	          layout( location = 9 ) out highp vec4 outFragColor;
129	        #else
130	          layout( location = 9 ) out highp vec4 outNOP9;
131	        #endif
132	 #endif 
133	
134	 #if 10<=BOUND_DRAW_BUFFER  
135	        #if BOUND_DRAW_BUFFER == 10
136	          layout( location = 10 ) out highp vec4 outFragColor;
137	        #else
138	          layout( location = 10 ) out highp vec4 outNOP10;
139	        #endif
140	 #endif 
141	
142	 #if 11<=BOUND_DRAW_BUFFER  
143	        #if BOUND_DRAW_BUFFER == 11
144	          layout( location = 11 ) out highp vec4 outFragColor;
145	        #else
146	          layout( location = 11 ) out highp vec4 outNOP11;
147	        #endif
148	 #endif 
149	
150	 #if 12<=BOUND_DRAW_BUFFER  
151	        #if BOUND_DRAW_BUFFER == 12
152	          layout( location = 12 ) out highp vec4 outFragColor;
153	        #else
154	          layout( location = 12 ) out highp vec4 outNOP12;
155	        #endif
156	 #endif 
157	
158	 #if 13<=BOUND_DRAW_BUFFER  
159	        #if BOUND_DRAW_BUFFER == 13
160	          layout( location = 13 ) out highp vec4 outFragColor;
161	        #else
162	          layout( location = 13 ) out highp vec4 outNOP13;
163	        #endif
164	 #endif 
165	
166	 #if 14<=BOUND_DRAW_BUFFER  
167	        #if BOUND_DRAW_BUFFER == 14
168	          layout( location = 14 ) out highp vec4 outFragColor;
169	        #else
170	          layout( location = 14 ) out highp vec4 outNOP14;
171	        #endif
172	 #endif 
173	    #else
174	      out highp vec4 outFragColor;
175	    #endif
176	  #else
177	    out vec4 outFragColor;
178	  #endif
179	#endif
180	
181	#  define texture1D texture
182	#  define texture2D texture
183	#  define texture3D texture
184	#  define textureCube texture
185	#  define texture2DLod textureLod
186	#  define textureCubeLod textureLod
187	#  define texture2DArray texture
188	#  if defined VERTEX_SHADER
189	#    define varying out
190	#    define attribute in
191	#  elif defined FRAGMENT_SHADER
192	#    define varying in
193	#    define gl_FragColor outFragColor
194	#  endif
195	#else
196	#  define isnan(val) !(val<0.0||val>0.0||val==0.0)
197	#endif
198	
199	#if __VERSION__ == 110
200	mat3 mat3_sub(mat4 m) {
201	  return mat3(m[0].xyz, m[1].xyz, m[2].xyz);
202	}
203	#else
204	 #define mat3_sub mat3
205	#endif
206	
207	#if __VERSION__ <= 140
208	float determinant(mat2 m) {
209	  return m[0][0] * m[1][1] - m[1][0] * m[0][1];
210	}
211	
212	float determinant(mat3 m) {
213	  return  + m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1])
214	          - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0])
215	          + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
216	}
217	#endif
218	
219	#if __VERSION__ <= 130
220	mat2 inverse(mat2 m) {
221	  return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / determinant(m);
222	}
223	
224	mat3 inverse(mat3 m) {
225	  return mat3(
226	    + (m[1][1] * m[2][2] - m[2][1] * m[1][2]),
227	    - (m[1][0] * m[2][2] - m[2][0] * m[1][2]),
228	    + (m[1][0] * m[2][1] - m[2][0] * m[1][1]),
229	    - (m[0][1] * m[2][2] - m[2][1] * m[0][2]),
230	    + (m[0][0] * m[2][2] - m[2][0] * m[0][2]),
231	    - (m[0][0] * m[2][1] - m[2][0] * m[0][1]),
232	    + (m[0][1] * m[1][2] - m[1][1] * m[0][2]),
233	    - (m[0][0] * m[1][2] - m[1][0] * m[0][2]),
234	    + (m[0][0] * m[1][1] - m[1][0] * m[0][1])) / determinant(m);
235	}
236	#endif
237	// -- end import Common/ShaderLib/GLSLCompat.glsllib --
238	// -- begin import Common/ShaderLib/Instancing.glsllib --
239	// Instancing GLSL library.
240	// 
241	// When the INSTANCING define is set in the shader, 
242	// all global matrices are replaced with "instanced" versions.
243	// One exception is g_NormalMatrix which becomes unusable,
244	// instead the function ApplyNormalTransform is used to transform
245	// the normal and tangent vectors into world view space.
246	
247	// The world matrix and normal transform quaternion need to be passed
248	// as vertex attributes "inWorldMatrix" and "inNormalRotationQuaternion"
249	// respectively. 
250	// The VertexBuffers for those two attributes 
251	// need to be configured into instanced mode (VertexBuffer.setInstanced(true)). 
252	//  - inWorldMatrix should have 12 * numInstances floats.
253	//  - inNormalRotationQuaternion should have 4 * numInstances.
254	// Thus, instancing data occupies 4 vertex attributes (16 / 4 = 4).
255	// 
256	// The GL_ARB_draw_instanced and GL_ARB_instanced_arrays extensions 
257	// are required (OGL 3.3).
258	
259	uniform mat4 g_WorldMatrix;
260	uniform mat4 g_ViewMatrix;
261	uniform mat4 g_ProjectionMatrix;
262	uniform mat4 g_WorldViewMatrix;
263	uniform mat4 g_WorldViewProjectionMatrix;
264	uniform mat4 g_ViewProjectionMatrix;
265	uniform mat3 g_NormalMatrix;
266	uniform mat3 g_WorldNormalMatrix;
267	
268	#if defined INSTANCING
269	
270	// World Matrix + Normal Rotation Quaternion. 
271	// The World Matrix is the top 3 rows - 
272	//     since the bottom row is always 0,0,0,1 for this transform.
273	// The bottom row is the transpose of the inverse of WorldView Transform 
274	//     as a quaternion. i.e. g_NormalMatrix converted to a quaternion.
275	//
276	// Using a quaternion instead of a matrix here allows saving approximately
277	// 2 vertex attributes which now can be used for additional per-vertex data.
278	attribute mat4 inInstanceData;
279	
280	
281	
282	vec4 TransformWorld(vec4 position)
283	{
284	    // Extract the world matrix out of the instance data, leaving out the
285	    // quaternion at the end.
286	    mat4 worldMatrix = mat4(vec4(inInstanceData[0].xyz, 0.0),
287	    vec4(inInstanceData[1].xyz, 0.0),
288	    vec4(inInstanceData[2].xyz, 0.0),
289	    vec4(inInstanceData[3].xyz, 1.0));
290	    return (worldMatrix * position);
291	}
292	
293	vec4 TransformWorldView(vec4 position)
294	{
295	    return g_ViewMatrix * TransformWorld(position);
296	}
297	
298	vec4 TransformWorldViewProjection(vec4 position)
299	{
300	    return g_ViewProjectionMatrix * TransformWorld(position);
301	}
302	
303	vec3 TransformWorldNormal(vec3 vec) {
304	    vec4 quat = vec4(inInstanceData[0].w, inInstanceData[1].w,
305	                     inInstanceData[2].w, inInstanceData[3].w);
306	
307	    return vec + vec3(2.0) * cross(cross(vec, quat.xyz) + vec3(quat.w) * vec, quat.xyz);
308	}
309	
310	vec3 TransformNormal(vec3 vec)
311	{
312	    return (g_ViewMatrix * vec4(TransformWorldNormal(vec), 0.0)).xyz;
313	}
314	
315	// Prevent user from using g_** matrices which will have invalid data in this case.
316	#define g_WorldMatrix               Use_the_instancing_functions_for_this
317	#define g_WorldViewMatrix           Use_the_instancing_functions_for_this
318	#define g_WorldViewProjectionMatrix Use_the_instancing_functions_for_this
319	#define g_NormalMatrix              Use_the_instancing_functions_for_this
320	
321	#else
322	
323	vec4 TransformWorld(vec4 position)
324	{
325	    return g_WorldMatrix * position;
326	}
327	
328	vec4 TransformWorldView(vec4 position)
329	{
330	    return g_WorldViewMatrix * position;
331	}
332	
333	vec4 TransformWorldViewProjection(vec4 position)
334	{
335	    return g_WorldViewProjectionMatrix * position;
336	}
337	
338	vec3 TransformNormal(vec3 normal) {
339		return g_NormalMatrix * normal;
340	}
341	
342	vec3 TransformWorldNormal(vec3 normal) {
343	    return normalize(g_WorldNormalMatrix * normal);
344	}
345	
346	 
347	#endif
348	// -- end import Common/ShaderLib/Instancing.glsllib --
349	// -- begin import Common/ShaderLib/Skinning.glsllib --
350	#ifdef NUM_BONES
351	
352	#if NUM_BONES < 1 || NUM_BONES > 255
353	#error NUM_BONES must be between 1 and 255.
354	#endif
355	
356	#define NUM_WEIGHTS_PER_VERT 4
357	 
358	attribute vec4 inHWBoneWeight;
359	attribute vec4 inHWBoneIndex;
360	uniform mat4 m_BoneMatrices[NUM_BONES];
361	
362	void Skinning_Compute(inout vec4 position){
363	    if (inHWBoneWeight.x != 0.0) {
364	#if NUM_WEIGHTS_PER_VERT == 1
365	        position = m_BoneMatrices[int(inHWBoneIndex.x)] * position;
366	#else
367	        mat4 mat = mat4(0.0);
368	        mat += m_BoneMatrices[int(inHWBoneIndex.x)] * inHWBoneWeight.x;
369	        mat += m_BoneMatrices[int(inHWBoneIndex.y)] * inHWBoneWeight.y;
370	        mat += m_BoneMatrices[int(inHWBoneIndex.z)] * inHWBoneWeight.z;
371	        mat += m_BoneMatrices[int(inHWBoneIndex.w)] * inHWBoneWeight.w;
372	        position = mat * position;
373	#endif
374	    }
375	}
376	 
377	void Skinning_Compute(inout vec4 position, inout vec3 normal){
378	    if (inHWBoneWeight.x != 0.0) {
379	#if NUM_WEIGHTS_PER_VERT == 1
380	        position = m_BoneMatrices[int(inHWBoneIndex.x)] * position;
381	        normal = (mat3(m_BoneMatrices[int(inHWBoneIndex.x)][0].xyz,
382	                       m_BoneMatrices[int(inHWBoneIndex.x)][1].xyz,
383	                       m_BoneMatrices[int(inHWBoneIndex.x)][2].xyz) * normal);
384	#else
385	        mat4 mat = mat4(0.0);
386	        mat += m_BoneMatrices[int(inHWBoneIndex.x)] * inHWBoneWeight.x;
387	        mat += m_BoneMatrices[int(inHWBoneIndex.y)] * inHWBoneWeight.y;
388	        mat += m_BoneMatrices[int(inHWBoneIndex.z)] * inHWBoneWeight.z;
389	        mat += m_BoneMatrices[int(inHWBoneIndex.w)] * inHWBoneWeight.w;
390	        position = mat * position;
391	
392	        mat3 rotMat = mat3(mat[0].xyz, mat[1].xyz, mat[2].xyz);
393	        normal = rotMat * normal;
394	#endif
395	    }
396	}
397	 
398	void Skinning_Compute(inout vec4 position, inout vec3 normal, inout vec3 tangent){
399	    if (inHWBoneWeight.x != 0.0) {
400	#if NUM_WEIGHTS_PER_VERT == 1
401	        position = m_BoneMatrices[int(inHWBoneIndex.x)] * position;
402	
403	        mat3 rotMat = mat3(m_BoneMatrices[int(inHWBoneIndex.x)][0].xyz,
404	                       m_BoneMatrices[int(inHWBoneIndex.x)][1].xyz,
405	                       m_BoneMatrices[int(inHWBoneIndex.x)][2].xyz);
406	        tangent = rotMat * tangent;
407	        normal = rotMat * normal;
408	#else
409	        mat4 mat = mat4(0.0);
410	        mat += m_BoneMatrices[int(inHWBoneIndex.x)] * inHWBoneWeight.x;
411	        mat += m_BoneMatrices[int(inHWBoneIndex.y)] * inHWBoneWeight.y;
412	        mat += m_BoneMatrices[int(inHWBoneIndex.z)] * inHWBoneWeight.z;
413	        mat += m_BoneMatrices[int(inHWBoneIndex.w)] * inHWBoneWeight.w;
414	        position = mat * position;
415	
416	        mat3 rotMat = mat3(mat[0].xyz, mat[1].xyz, mat[2].xyz);
417	        tangent = rotMat * tangent;
418	        normal = rotMat * normal;
419	#endif
420	    }
421	}
422	
423	#endif
424	// -- end import Common/ShaderLib/Skinning.glsllib --
425	// -- begin import Common/ShaderLib/Lighting.glsllib --
426	/*Common function for light calculations*/
427	
428	
429	/*
430	* Computes light direction 
431	* lightType should be 0.0,1.0,2.0, respectively for Directional, point and spot lights.
432	* Outputs the light direction and the light half vector. 
433	*/
434	void lightComputeDir(in vec3 worldPos, in float lightType, in vec4 position, out vec4 lightDir, out vec3 lightVec){
435	    float posLight = step(0.5, lightType);    
436	    vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
437	    lightVec = tempVec;          
438	    float dist = length(tempVec);
439	#ifdef SRGB
440	    lightDir.w = (1.0 - position.w * dist) / (1.0 + position.w * dist * dist);
441	    lightDir.w = clamp(lightDir.w, 1.0 - posLight, 1.0);
442	#else
443	    lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
444	#endif
445	    lightDir.xyz = tempVec / vec3(dist);
446	}
447	
448	/*
449	* Computes the spot falloff for a spotlight
450	*/
451	float computeSpotFalloff(in vec4 lightDirection, in vec3 lightVector){
452	    vec3 L=normalize(lightVector);
453	    vec3 spotdir = normalize(lightDirection.xyz);
454	    float curAngleCos = dot(-L, spotdir);    
455	    float innerAngleCos = floor(lightDirection.w) * 0.001;
456	    float outerAngleCos = fract(lightDirection.w);
457	    float innerMinusOuter = innerAngleCos - outerAngleCos;
458	    float falloff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, step(lightDirection.w, 0.001), 1.0);
459	
460	#ifdef SRGB
461	    // Use quadratic falloff (notice the ^4)
462	    return pow(clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0), 4.0);
463	#else
464	    // Use linear falloff
465	    return falloff;
466	#endif
467	}
468	
469	// -- end import Common/ShaderLib/Lighting.glsllib --
470	// -- begin import Common/ShaderLib/MorphAnim.glsllib --
471	/**
472	A glsllib that perform morph animation.
473	Note that it only handles morphing position, normals and tangents.
474	*/
475	#ifdef NUM_MORPH_TARGETS
476	    #define NUM_BUFFERS NUM_MORPH_TARGETS * NUM_TARGETS_BUFFERS
477	    #if (NUM_BUFFERS > 0)
478	        uniform float m_MorphWeights[NUM_MORPH_TARGETS];
479	        attribute vec3 inMorphTarget0;
480	    #endif
481	    #if (NUM_BUFFERS > 1)
482	        attribute vec3 inMorphTarget1;
483	    #endif
484	    #if (NUM_BUFFERS > 2)
485	        attribute vec3 inMorphTarget2;
486	    #endif
487	    #if (NUM_BUFFERS > 3)
488	        attribute vec3 inMorphTarget3;
489	    #endif
490	    #if (NUM_BUFFERS > 4)
491	        attribute vec3 inMorphTarget4;
492	    #endif
493	    #if (NUM_BUFFERS > 5)
494	        attribute vec3 inMorphTarget5;
495	    #endif
496	    #if (NUM_BUFFERS > 6)
497	        attribute vec3 inMorphTarget6;
498	    #endif
499	    #if (NUM_BUFFERS > 7)
500	        attribute vec3 inMorphTarget7;
501	    #endif
502	    #if (NUM_BUFFERS > 8)
503	        attribute vec3 inMorphTarget8;
504	    #endif
505	    #if (NUM_BUFFERS > 9)
506	        attribute vec3 inMorphTarget9;
507	    #endif
508	    #if (NUM_BUFFERS > 10)
509	        attribute vec3 inMorphTarget10;
510	    #endif
511	    #if (NUM_BUFFERS > 11)
512	        attribute vec3 inMorphTarget11;
513	    #endif
514	    #if (NUM_BUFFERS > 12)
515	        attribute vec3 inMorphTarget12;
516	    #endif
517	    #if (NUM_BUFFERS > 13)
518	        attribute vec3 inMorphTarget13;
519	    #endif
520	
521	    void Morph_Compute_Pos(inout vec4 pos){
522	        #if (NUM_TARGETS_BUFFERS == 1)
523	            #if (NUM_MORPH_TARGETS > 0)
524	                pos.xyz += m_MorphWeights[0] * inMorphTarget0;
525	            #endif
526	            #if (NUM_MORPH_TARGETS > 1)
527	                pos.xyz += m_MorphWeights[1] * inMorphTarget1;
528	            #endif
529	            #if (NUM_MORPH_TARGETS > 2)
530	                pos.xyz += m_MorphWeights[2] * inMorphTarget2;
531	            #endif
532	            #if (NUM_MORPH_TARGETS > 3)
533	                pos.xyz += m_MorphWeights[3] * inMorphTarget3;
534	            #endif
535	            #if (NUM_MORPH_TARGETS > 4)
536	                pos.xyz += m_MorphWeights[4] * inMorphTarget4;
537	            #endif
538	            #if (NUM_MORPH_TARGETS > 5)
539	                pos.xyz += m_MorphWeights[5] * inMorphTarget5;
540	            #endif
541	            #if (NUM_MORPH_TARGETS > 6)
542	                pos.xyz += m_MorphWeights[6] * inMorphTarget6;
543	            #endif
544	            #if (NUM_MORPH_TARGETS > 7)
545	                pos.xyz += m_MorphWeights[7] * inMorphTarget7;
546	            #endif
547	            #if (NUM_MORPH_TARGETS > 8)
548	                pos.xyz += m_MorphWeights[8] * inMorphTarget8;
549	            #endif
550	            #if (NUM_MORPH_TARGETS > 9)
551	                pos.xyz += m_MorphWeights[9] * inMorphTarget9;
552	            #endif
553	            #if (NUM_MORPH_TARGETS > 10)
554	                pos.xyz += m_MorphWeights[10] * inMorphTarget10;
555	            #endif
556	            #if (NUM_MORPH_TARGETS > 11)
557	                pos.xyz += m_MorphWeights[11] * inMorphTarget11;
558	            #endif
559	            #if (NUM_MORPH_TARGETS > 12)
560	                pos.xyz += m_MorphWeights[12] * inMorphTarget12;
561	            #endif
562	            #if (NUM_MORPH_TARGETS > 13)
563	                pos.xyz += m_MorphWeights[13] * inMorphTarget13;
564	            #endif
565	        #endif
566	    }
567	
568	    float Get_Inverse_Weights_Sum(){
569	        float sum = 0.0;
570	        for( int i = 0;i < NUM_MORPH_TARGETS; i++){
571	            sum += m_MorphWeights[i];
572	        }
573	        return 1.0 / max(1.0, sum);
574	    }
575	
576	    void Morph_Compute_Pos_Norm(inout vec4 pos, inout vec3 norm){
577	        #if (NUM_TARGETS_BUFFERS == 2)
578	            // weight sum may be over 1.0. It's totally valid for position
579	            // but for normals. the weights needs to be normalized.
580	            float invWeightsSum = Get_Inverse_Weights_Sum();
581	            #if (NUM_BUFFERS > 1)
582	                pos.xyz += m_MorphWeights[0] * inMorphTarget0;
583	                norm += m_MorphWeights[0] * invWeightsSum * inMorphTarget1;
584	            #endif
585	            #if (NUM_BUFFERS > 3)
586	                pos.xyz += m_MorphWeights[1] * inMorphTarget2;
587	                norm.xyz += m_MorphWeights[1] * invWeightsSum * inMorphTarget3;
588	            #endif
589	            #if (NUM_BUFFERS > 5)
590	                pos.xyz += m_MorphWeights[2] * inMorphTarget4;
591	                norm += m_MorphWeights[2] * invWeightsSum * inMorphTarget5;
592	            #endif
593	            #if (NUM_BUFFERS > 7)
594	                pos.xyz += m_MorphWeights[3] * inMorphTarget6;
595	                norm += m_MorphWeights[3] * invWeightsSum * inMorphTarget7;
596	            #endif
597	            #if (NUM_BUFFERS > 9)
598	                pos.xyz += m_MorphWeights[4] * inMorphTarget8;
599	                norm += m_MorphWeights[4] * invWeightsSum * inMorphTarget9;
600	            #endif
601	            #if (NUM_BUFFERS > 11)
602	                pos.xyz += m_MorphWeights[5] * inMorphTarget10;
603	                norm += m_MorphWeights[5] * invWeightsSum * inMorphTarget11;
604	            #endif
605	            #if (NUM_BUFFERS > 13)
606	                pos.xyz += m_MorphWeights[6] * inMorphTarget12;
607	                norm += m_MorphWeights[6] * invWeightsSum * inMorphTarget13;
608	            #endif
609	        #endif
610	    }
611	
612	    void Morph_Compute_Pos_Norm_Tan(inout vec4 pos, inout vec3 norm, inout vec3 tan){
613	        #if (NUM_TARGETS_BUFFERS == 3)
614	            // weight sum may be over 1.0. It's totally valid for position
615	            // but for normals. the weights needs to be normalized.
616	            float invWeightsSum = Get_Inverse_Weights_Sum();
617	            #if (NUM_BUFFERS > 2)
618	                float normWeight =  m_MorphWeights[0] * invWeightsSum;
619	                pos.xyz += m_MorphWeights[0] * inMorphTarget0;
620	                norm += normWeight * inMorphTarget1;
621	                tan += normWeight * inMorphTarget2;
622	            #endif
623	            #if (NUM_BUFFERS > 5)
624	                float normWeight =  m_MorphWeights[1] * invWeightsSum;
625	                pos.xyz += m_MorphWeights[1] * inMorphTarget3;
626	                norm += normWeight * inMorphTarget4;
627	                tan += normWeight * inMorphTarget5;
628	            #endif
629	            #if (NUM_BUFFERS > 8)
630	                float normWeight =  m_MorphWeights[2] * invWeightsSum;
631	                pos.xyz += m_MorphWeights[2] * inMorphTarget6;
632	                norm += normWeight * inMorphTarget7;
633	                tan += normWeight * inMorphTarget8;
634	            #endif
635	            #if (NUM_BUFFERS > 11)
636	                float normWeight =  m_MorphWeights[3] * invWeightsSum;
637	                pos.xyz += m_MorphWeights[3] * inMorphTarget9;
638	                norm += normWeight * inMorphTarget10;
639	                tan += normWeight * inMorphTarget11;
640	            #endif
641	        #endif
642	    }
643	
644	    void Morph_Compute(inout vec4 pos){
645	        #if (NUM_TARGETS_BUFFERS == 2)
646	            vec3 dummy_norm = vec3(0.0);
647	            Morph_Compute_Pos_Norm(pos, dummy_norm);
648	            return;
649	        #elif (NUM_TARGETS_BUFFERS == 3)
650	            vec3 dummy_norm = vec3(0.0);
651	            vec3 dummy_tan = vec3(0.0);
652	            Morph_Compute_Pos_Norm_Tan(pos, dummy_norm, dummy_tan);
653	            return;
654	        #endif
655	        Morph_Compute_Pos(pos);
656	    }
657	
658	    void Morph_Compute(inout vec4 pos, inout vec3 norm){
659	        #if (NUM_TARGETS_BUFFERS == 1)
660	            Morph_Compute_Pos(pos);
661	            return;
662	        #elif (NUM_TARGETS_BUFFERS == 3)
663	            vec3 dummy_norm = vec3(0.0);
664	            vec3 dummy_tan = vec3(0.0);
665	            Morph_Compute_Pos_Norm_Tan(pos, dummy_norm, dummy_tan);
666	            return;
667	        #elif  (NUM_TARGETS_BUFFERS == 2)
668	            Morph_Compute_Pos_Norm(pos, norm);
669	        #endif
670	    }
671	
672	    void Morph_Compute(inout vec4 pos, inout vec3 norm, inout vec3 tan){
673	        #if (NUM_TARGETS_BUFFERS == 1)
674	            Morph_Compute_Pos(pos);
675	            return;
676	        #elif (NUM_TARGETS_BUFFERS == 2)
677	            Morph_Compute_Pos_Norm(pos, norm);
678	            tan = normalize(tan - dot(tan, norm) * norm);
679	            return;
680	        #elif (NUM_TARGETS_BUFFERS == 3)
681	            Morph_Compute_Pos_Norm_Tan(pos, norm, tan);
682	        #endif
683	    }
684	
685	#endif
686	// -- end import Common/ShaderLib/MorphAnim.glsllib --
687	
688	#ifdef VERTEX_LIGHTING
689	// -- begin import Common/ShaderLib/BlinnPhongLighting.glsllib --
690	/*Blinn Phong lighting*/
691	
692	/*
693	* Computes diffuse factor (Lambert)
694	*/
695	float lightComputeDiffuse(in vec3 norm, in vec3 lightdir){
696	    return max(0.0, dot(norm, lightdir));
697	}
698	
699	/*
700	* Computes specular factor   (blinn phong) 
701	*/
702	float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){
703	    vec3 H = normalize(viewdir + lightdir);
704	    float HdotN = max(0.0, dot(H, norm));
705	    return pow(HdotN, shiny);
706	}
707	
708	/*
709	*Computes standard phong specular lighting
710	*/
711	float lightComputeSpecularPhong(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){
712	    vec3 R = reflect(-lightdir, norm);
713	    return pow(max(dot(R, viewdir), 0.0), shiny);
714	}
715	
716	
717	/*
718	* Computes diffuse and specular factors and pack them in a vec2 (x=diffuse, y=specular)
719	*/
720	vec2 computeLighting(in vec3 norm, in vec3 viewDir, in vec3 lightDir, in float attenuation, in float shininess){
721	   float diffuseFactor = lightComputeDiffuse(norm, lightDir);
722	   float specularFactor = lightComputeSpecular(norm, viewDir, lightDir, shininess);      
723	   if (shininess <= 1.0) {
724	       specularFactor = 0.0; // should be one instruction on most cards ..
725	   }
726	   specularFactor *= diffuseFactor;
727	   return vec2(diffuseFactor, specularFactor) * vec2(attenuation);
728	}
729	// -- end import Common/ShaderLib/BlinnPhongLighting.glsllib --
730	#endif
731	
732	// fog - jayfella
733	#ifdef USE_FOG
734	    varying float fogDistance;
735	    uniform vec3 g_CameraPosition;
736	#endif
737	
738	uniform vec4 m_Ambient;
739	uniform vec4 m_Diffuse;
740	uniform vec4 m_Specular;
741	uniform float m_Shininess;
742	
743	uniform vec4 g_LightColor;
744	uniform vec4 g_LightPosition;
745	uniform vec4 g_AmbientLightColor;
746	
747	varying vec2 texCoord;
748	#ifdef SEPARATE_TEXCOORD
749	  varying vec2 texCoord2;
750	  attribute vec2 inTexCoord2;
751	#endif
752	
753	varying vec3 AmbientSum;
754	varying vec4 DiffuseSum;
755	varying vec3 SpecularSum;
756	
757	attribute vec3 inPosition;
758	attribute vec2 inTexCoord;
759	attribute vec3 inNormal;
760	
761	varying vec3 lightVec;
762	
763	#ifdef VERTEX_COLOR
764	  attribute vec4 inColor;
765	#endif
766	
767	#ifndef VERTEX_LIGHTING
768	  attribute vec4 inTangent;
769	
770	  #ifndef NORMALMAP
771	    varying vec3 vNormal;
772	  #endif  
773	  varying vec3 vViewDir;
774	  varying vec4 vLightDir;
775	#else
776	  varying vec2 vertexLightValues;
777	  uniform vec4 g_LightDirection;
778	#endif
779	
780	#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING) 
781	    varying vec3 vViewDirPrlx;
782	#endif
783	
784	#ifdef USE_REFLECTION
785	    uniform vec3 g_CameraPosition;
786	
787	    uniform vec3 m_FresnelParams;
788	    varying vec4 refVec;
789	
790	    /**
791	     * Input:
792	     * attribute inPosition
793	     * attribute inNormal
794	     * uniform g_WorldMatrix
795	     * uniform g_CameraPosition
796	     *
797	     * Output:
798	     * varying refVec
799	     */
800	    void computeRef(in vec4 modelSpacePos){
801	        // vec3 worldPos = (g_WorldMatrix * modelSpacePos).xyz;
802	        vec3 worldPos = TransformWorld(modelSpacePos).xyz;
803	
804	        vec3 I = normalize( g_CameraPosition - worldPos  ).xyz;
805	        // vec3 N = normalize( (g_WorldMatrix * vec4(inNormal, 0.0)).xyz );
806	        vec3 N = normalize( TransformWorld(vec4(inNormal, 0.0)).xyz );
807	
808	        refVec.xyz = reflect(I, N);
809	        refVec.w   = m_FresnelParams.x + m_FresnelParams.y * pow(1.0 + dot(I, N), m_FresnelParams.z);
810	    }
811	#endif
812	
813	void main(){
814	   vec4 modelSpacePos = vec4(inPosition, 1.0);
815	   vec3 modelSpaceNorm = inNormal;
816	   
817	   #ifndef VERTEX_LIGHTING
818	        vec3 modelSpaceTan  = inTangent.xyz;
819	   #endif
820	
821	   #ifdef NUM_MORPH_TARGETS
822	        #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
823	           Morph_Compute(modelSpacePos, modelSpaceNorm, modelSpaceTan);
824	        #else
825	           Morph_Compute(modelSpacePos, modelSpaceNorm);
826	        #endif
827	   #endif
828	
829	   #ifdef NUM_BONES
830	        #ifndef VERTEX_LIGHTING
831	        Skinning_Compute(modelSpacePos, modelSpaceNorm, modelSpaceTan);
832	        #else
833	        Skinning_Compute(modelSpacePos, modelSpaceNorm);
834	        #endif
835	   #endif
836	
837	   gl_Position = TransformWorldViewProjection(modelSpacePos);// g_WorldViewProjectionMatrix * modelSpacePos;
838	   texCoord = inTexCoord;
839	   #ifdef SEPARATE_TEXCOORD
840	      texCoord2 = inTexCoord2;
841	   #endif
842	
843	   vec3 wvPosition = TransformWorldView(modelSpacePos).xyz;// (g_WorldViewMatrix * modelSpacePos).xyz;
844	   vec3 wvNormal  = normalize(TransformNormal(modelSpaceNorm));//normalize(g_NormalMatrix * modelSpaceNorm);
845	   vec3 viewDir = normalize(-wvPosition);
846	  
847	   vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz,clamp(g_LightColor.w,0.0,1.0)));
848	   wvLightPos.w = g_LightPosition.w;
849	   vec4 lightColor = g_LightColor;
850	
851	   #if (defined(NORMALMAP) || defined(PARALLAXMAP)) && !defined(VERTEX_LIGHTING)
852	     vec3 wvTangent = normalize(TransformNormal(modelSpaceTan));
853	     vec3 wvBinormal = cross(wvNormal, wvTangent);
854	     mat3 tbnMat = mat3(wvTangent, wvBinormal * inTangent.w,wvNormal);
855	   #endif
856	 
857	   #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
858	     vViewDir  = -wvPosition * tbnMat;    
859	     #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) 
860	         vViewDirPrlx = vViewDir;
861	     #endif
862	     lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
863	     vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz;
864	   #elif !defined(VERTEX_LIGHTING)
865	     vNormal = wvNormal;
866	     vViewDir = viewDir;
867	     #if defined(PARALLAXMAP)
868	        vViewDirPrlx  =  -wvPosition * tbnMat;
869	     #endif
870	     lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
871	   #endif
872	
873	   #ifdef MATERIAL_COLORS
874	      AmbientSum  = (m_Ambient  * g_AmbientLightColor).rgb;
875	      DiffuseSum  =  m_Diffuse  * vec4(lightColor.rgb, 1.0);
876	      SpecularSum = (m_Specular * lightColor).rgb;
877	    #else
878	      // Defaults: Ambient and diffuse are white, specular is black.
879	      AmbientSum  = g_AmbientLightColor.rgb;
880	      DiffuseSum  =  vec4(lightColor.rgb, 1.0);
881	      SpecularSum = vec3(0.0);
882	    #endif
883	
884	    #ifdef VERTEX_COLOR
885	      AmbientSum *= inColor.rgb;
886	      DiffuseSum *= inColor;
887	    #endif
888	
889	    #ifdef VERTEX_LIGHTING
890	        float spotFallOff = 1.0;
891	        vec4 vLightDir;
892	        lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
893	        #if __VERSION__ >= 110
894	            // allow use of control flow
895	        if(lightColor.w > 1.0){
896	        #endif           
897	           spotFallOff = computeSpotFalloff(g_LightDirection, lightVec);
898	        #if __VERSION__ >= 110           
899	        }
900	        #endif
901	        
902	        vertexLightValues = computeLighting(wvNormal, viewDir, vLightDir.xyz, vLightDir.w * spotFallOff, m_Shininess);
903	    #endif
904	
905	    #ifdef USE_REFLECTION 
906	        computeRef(modelSpacePos);
907	    #endif
908	
909	    #ifdef USE_FOG
910	        fogDistance = distance(g_CameraPosition, (TransformWorld(modelSpacePos)).xyz);
911	    #endif
912	}

Dec 07, 2025 11:51:23 AM com.jme3.app.LegacyApplication handleError
SEVERE: Uncaught exception thrown in Thread[jME3 Main,5,main]
com.jme3.renderer.RendererException: compile error in: ShaderSource[name=Common/MatDefs/Light/Lighting.vert, defines, type=Vertex, language=GLSL150]
0(353) : error C0000: NUM_BONES must be between 1 and 255.
0(360) : error C1043: size of dimension cannot be less than 1

	at com.jme3.renderer.opengl.GLRenderer.updateShaderSourceData(GLRenderer.java:1661)
	at com.jme3.renderer.opengl.GLRenderer.updateShaderData(GLRenderer.java:1688)
	at com.jme3.renderer.opengl.GLRenderer.setShader(GLRenderer.java:1753)
	at com.jme3.material.logic.MultiPassLightingLogic.render(MultiPassLightingLogic.java:159)
	at com.jme3.material.Technique.render(Technique.java:168)
	at com.jme3.material.Material.render(Material.java:1122)
	at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:832)
	at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:761)
	at com.jme3.renderer.queue.RenderQueue.renderGeometryList(RenderQueue.java:273)
	at com.jme3.renderer.queue.RenderQueue.renderQueue(RenderQueue.java:315)
	at com.jme3.renderer.RenderManager.renderViewPortQueues(RenderManager.java:1106)
	at com.jme3.renderer.RenderManager.flushQueue(RenderManager.java:1002)
	at com.jme3.renderer.pipeline.ForwardPipeline.pipelineRender(ForwardPipeline.java:117)
	at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1303)
	at com.jme3.renderer.RenderManager.render(RenderManager.java:1345)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:296)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:163)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:246)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:245)
	at java.base/java.lang.Thread.run(Thread.java:840)

Dec 07, 2025 11:51:23 AM com.jme3.audio.openal.ALAudioRenderer destroyOpenAL
INFO: OpenAL context destroyed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething that is supposed to work, but doesn't. More severe than a "defect".

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions