action-engine-js 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +45 -0
- package/README.md +348 -0
- package/actionengine/3rdparty/goblin/goblin.js +9609 -0
- package/actionengine/3rdparty/goblin/goblin.min.js +5 -0
- package/actionengine/camera/actioncamera.js +90 -0
- package/actionengine/camera/cameracollisionhandler.js +69 -0
- package/actionengine/character/actioncharacter.js +360 -0
- package/actionengine/character/actioncharacter3D.js +61 -0
- package/actionengine/core/app.js +430 -0
- package/actionengine/debug/basedebugpanel.js +858 -0
- package/actionengine/display/canvasmanager.js +75 -0
- package/actionengine/display/gl/programmanager.js +570 -0
- package/actionengine/display/gl/shaders/lineshader.js +118 -0
- package/actionengine/display/gl/shaders/objectshader.js +1756 -0
- package/actionengine/display/gl/shaders/particleshader.js +43 -0
- package/actionengine/display/gl/shaders/shadowshader.js +319 -0
- package/actionengine/display/gl/shaders/spriteshader.js +100 -0
- package/actionengine/display/gl/shaders/watershader.js +67 -0
- package/actionengine/display/graphics/actionmodel3D.js +191 -0
- package/actionengine/display/graphics/actionsprite3D.js +230 -0
- package/actionengine/display/graphics/lighting/actiondirectionalshadowlight.js +864 -0
- package/actionengine/display/graphics/lighting/actionlight.js +211 -0
- package/actionengine/display/graphics/lighting/actionomnidirectionalshadowlight.js +862 -0
- package/actionengine/display/graphics/lighting/lightingconstants.js +263 -0
- package/actionengine/display/graphics/lighting/lightmanager.js +789 -0
- package/actionengine/display/graphics/renderableobject.js +44 -0
- package/actionengine/display/graphics/renderers/actionrenderer2D.js +341 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/actionrenderer3D.js +655 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/canvasmanager3D.js +82 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/debugrenderer3D.js +493 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/objectrenderer3D.js +790 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/spriteRenderer3D.js +266 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/sunrenderer3D.js +140 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/waterrenderer3D.js +173 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/weatherrenderer3D.js +87 -0
- package/actionengine/display/graphics/texture/proceduraltexture.js +192 -0
- package/actionengine/display/graphics/texture/texturemanager.js +242 -0
- package/actionengine/display/graphics/texture/textureregistry.js +177 -0
- package/actionengine/input/actionscrollablearea.js +1405 -0
- package/actionengine/input/inputhandler.js +1647 -0
- package/actionengine/math/geometry/geometrybuilder.js +161 -0
- package/actionengine/math/geometry/glbexporter.js +364 -0
- package/actionengine/math/geometry/glbloader.js +722 -0
- package/actionengine/math/geometry/modelcodegenerator.js +97 -0
- package/actionengine/math/geometry/triangle.js +33 -0
- package/actionengine/math/geometry/triangleutils.js +34 -0
- package/actionengine/math/mathutils.js +25 -0
- package/actionengine/math/matrix4.js +785 -0
- package/actionengine/math/physics/actionphysics.js +108 -0
- package/actionengine/math/physics/actionphysicsobject3D.js +164 -0
- package/actionengine/math/physics/actionphysicsworld3D.js +238 -0
- package/actionengine/math/physics/actionraycast.js +129 -0
- package/actionengine/math/physics/shapes/actionphysicsbox3D.js +158 -0
- package/actionengine/math/physics/shapes/actionphysicscapsule3D.js +200 -0
- package/actionengine/math/physics/shapes/actionphysicscompoundshape3D.js +147 -0
- package/actionengine/math/physics/shapes/actionphysicscone3D.js +126 -0
- package/actionengine/math/physics/shapes/actionphysicsconvexshape3D.js +72 -0
- package/actionengine/math/physics/shapes/actionphysicscylinder3D.js +117 -0
- package/actionengine/math/physics/shapes/actionphysicsmesh3D.js +74 -0
- package/actionengine/math/physics/shapes/actionphysicsplane3D.js +100 -0
- package/actionengine/math/physics/shapes/actionphysicssphere3D.js +95 -0
- package/actionengine/math/quaternion.js +61 -0
- package/actionengine/math/vector2.js +277 -0
- package/actionengine/math/vector3.js +318 -0
- package/actionengine/math/viewfrustum.js +136 -0
- package/actionengine/network/ACTIONNETREADME.md +810 -0
- package/actionengine/network/client/ActionNetManager.js +802 -0
- package/actionengine/network/client/ActionNetManagerGUI.js +1709 -0
- package/actionengine/network/client/ActionNetManagerP2P.js +1537 -0
- package/actionengine/network/client/SyncSystem.js +422 -0
- package/actionengine/network/p2p/ActionNetPeer.js +142 -0
- package/actionengine/network/p2p/ActionNetTrackerClient.js +623 -0
- package/actionengine/network/p2p/DataConnection.js +282 -0
- package/actionengine/network/p2p/README.md +510 -0
- package/actionengine/network/p2p/example.html +502 -0
- package/actionengine/network/server/ActionNetServer.js +577 -0
- package/actionengine/network/server/ActionNetServerSSL.js +579 -0
- package/actionengine/network/server/ActionNetServerUtils.js +458 -0
- package/actionengine/network/server/SERVERREADME.md +314 -0
- package/actionengine/network/server/package-lock.json +35 -0
- package/actionengine/network/server/package.json +13 -0
- package/actionengine/network/server/start.bat +27 -0
- package/actionengine/network/server/start.sh +25 -0
- package/actionengine/network/server/startwss.bat +27 -0
- package/actionengine/sound/audiomanager.js +1589 -0
- package/actionengine/sound/soundfont/ACTIONSOUNDFONT_README.md +205 -0
- package/actionengine/sound/soundfont/actionparser.js +718 -0
- package/actionengine/sound/soundfont/actionreverb.js +252 -0
- package/actionengine/sound/soundfont/actionsoundfont.js +543 -0
- package/actionengine/sound/soundfont/sf2playerlicence.txt +29 -0
- package/actionengine/sound/soundfont/soundfont.js +2 -0
- package/dist/action-engine.min.js +328 -0
- package/package.json +35 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// actionengine/display/graphics/renderers/actionrenderer3D/spriteRenderer3D.js
|
|
2
|
+
|
|
3
|
+
class SpriteRenderer3D {
|
|
4
|
+
constructor(gl, programManager, isWebGL2 = false) {
|
|
5
|
+
this.gl = gl;
|
|
6
|
+
this.programManager = programManager;
|
|
7
|
+
this.isWebGL2 = isWebGL2;
|
|
8
|
+
|
|
9
|
+
// Sprite shader and program
|
|
10
|
+
this.spriteShader = new SpriteShader();
|
|
11
|
+
this.program = null;
|
|
12
|
+
this.locations = {};
|
|
13
|
+
|
|
14
|
+
// Quad geometry for billboards
|
|
15
|
+
this.quadBuffer = null;
|
|
16
|
+
this.indexBuffer = null;
|
|
17
|
+
|
|
18
|
+
// Initialize
|
|
19
|
+
this._initializeShader();
|
|
20
|
+
this._createQuadGeometry();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initialize the billboard shader program
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
_initializeShader() {
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
this.program = this.programManager.createShaderProgram(
|
|
31
|
+
this.spriteShader.getVertexShader(this.isWebGL2),
|
|
32
|
+
this.spriteShader.getFragmentShader(this.isWebGL2),
|
|
33
|
+
'sprite_shader'
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// Get attribute and uniform locations
|
|
37
|
+
this.locations = {
|
|
38
|
+
// Attributes
|
|
39
|
+
position: this.gl.getAttribLocation(this.program, 'aPosition'),
|
|
40
|
+
texCoord: this.gl.getAttribLocation(this.program, 'aTexCoord'),
|
|
41
|
+
|
|
42
|
+
// Uniforms
|
|
43
|
+
projectionMatrix: this.gl.getUniformLocation(this.program, 'uProjectionMatrix'),
|
|
44
|
+
viewMatrix: this.gl.getUniformLocation(this.program, 'uViewMatrix'),
|
|
45
|
+
spritePosition: this.gl.getUniformLocation(this.program, 'uSpritePosition'),
|
|
46
|
+
spriteSize: this.gl.getUniformLocation(this.program, 'uSpriteSize'),
|
|
47
|
+
cameraPosition: this.gl.getUniformLocation(this.program, 'uCameraPosition'),
|
|
48
|
+
cameraRight: this.gl.getUniformLocation(this.program, 'uCameraRight'),
|
|
49
|
+
cameraUp: this.gl.getUniformLocation(this.program, 'uCameraUp'),
|
|
50
|
+
isBillboard: this.gl.getUniformLocation(this.program, 'uIsBillboard'),
|
|
51
|
+
spriteForward: this.gl.getUniformLocation(this.program, 'uSpriteForward'),
|
|
52
|
+
spriteUp: this.gl.getUniformLocation(this.program, 'uSpriteUp'),
|
|
53
|
+
texture: this.gl.getUniformLocation(this.program, 'uTexture'),
|
|
54
|
+
color: this.gl.getUniformLocation(this.program, 'uColor'),
|
|
55
|
+
alpha: this.gl.getUniformLocation(this.program, 'uAlpha')
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error('[SpriteRenderer3D] Failed to initialize shader:', error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Create quad geometry for billboard rendering
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
_createQuadGeometry() {
|
|
68
|
+
const gl = this.gl;
|
|
69
|
+
|
|
70
|
+
// Quad vertices (position + texture coordinates)
|
|
71
|
+
// Using a centered quad from -0.5 to 0.5
|
|
72
|
+
const vertices = new Float32Array([
|
|
73
|
+
// Position (x, y, z) Texture (u, v)
|
|
74
|
+
-0.5, -0.5, 0.0, 0.0, 0.0, // Bottom-left
|
|
75
|
+
0.5, -0.5, 0.0, 1.0, 0.0, // Bottom-right
|
|
76
|
+
0.5, 0.5, 0.0, 1.0, 1.0, // Top-right
|
|
77
|
+
-0.5, 0.5, 0.0, 0.0, 1.0 // Top-left
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
// Quad indices
|
|
81
|
+
const indices = new Uint16Array([
|
|
82
|
+
0, 1, 2, // First triangle
|
|
83
|
+
0, 2, 3 // Second triangle
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
// Create vertex buffer
|
|
87
|
+
this.quadBuffer = gl.createBuffer();
|
|
88
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);
|
|
89
|
+
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
|
|
90
|
+
|
|
91
|
+
// Create index buffer
|
|
92
|
+
this.indexBuffer = gl.createBuffer();
|
|
93
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
|
94
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
|
|
95
|
+
|
|
96
|
+
// Unbind buffers
|
|
97
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
98
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Render billboard sprites
|
|
103
|
+
* @param {Array} sprites - Array of ActionSprite3D objects
|
|
104
|
+
* @param {Object} camera - Camera object
|
|
105
|
+
* @param {Float32Array} projectionMatrix - Projection matrix
|
|
106
|
+
* @param {Float32Array} viewMatrix - View matrix
|
|
107
|
+
*/
|
|
108
|
+
render(sprites, camera, projectionMatrix, viewMatrix) {
|
|
109
|
+
if (!sprites || sprites.length === 0 || !this.program) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const gl = this.gl;
|
|
114
|
+
|
|
115
|
+
// Use billboard shader program
|
|
116
|
+
gl.useProgram(this.program);
|
|
117
|
+
|
|
118
|
+
// Set up vertex attributes
|
|
119
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);
|
|
120
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
|
121
|
+
|
|
122
|
+
// Position attribute (3 floats)
|
|
123
|
+
gl.enableVertexAttribArray(this.locations.position);
|
|
124
|
+
gl.vertexAttribPointer(this.locations.position, 3, gl.FLOAT, false, 5 * 4, 0);
|
|
125
|
+
|
|
126
|
+
// Texture coordinate attribute (2 floats)
|
|
127
|
+
gl.enableVertexAttribArray(this.locations.texCoord);
|
|
128
|
+
gl.vertexAttribPointer(this.locations.texCoord, 2, gl.FLOAT, false, 5 * 4, 3 * 4);
|
|
129
|
+
|
|
130
|
+
// Set common uniforms
|
|
131
|
+
gl.uniformMatrix4fv(this.locations.projectionMatrix, false, projectionMatrix);
|
|
132
|
+
gl.uniformMatrix4fv(this.locations.viewMatrix, false, viewMatrix);
|
|
133
|
+
|
|
134
|
+
// Calculate camera vectors for billboarding
|
|
135
|
+
const cameraVectors = this._calculateCameraVectors(camera);
|
|
136
|
+
gl.uniform3fv(this.locations.cameraPosition, camera.position.toArray());
|
|
137
|
+
gl.uniform3fv(this.locations.cameraRight, cameraVectors.right.toArray());
|
|
138
|
+
gl.uniform3fv(this.locations.cameraUp, cameraVectors.up.toArray());
|
|
139
|
+
|
|
140
|
+
// Enable blending for transparency
|
|
141
|
+
gl.enable(gl.BLEND);
|
|
142
|
+
gl.enable(gl.DEPTH_TEST);
|
|
143
|
+
|
|
144
|
+
// Ensure depth function matches the main 3D renderer for consistent depth testing
|
|
145
|
+
gl.depthFunc(gl.LEQUAL);
|
|
146
|
+
|
|
147
|
+
gl.depthMask(false); // Don't write to depth buffer for billboards
|
|
148
|
+
|
|
149
|
+
// Render each sprite
|
|
150
|
+
for (const sprite of sprites) {
|
|
151
|
+
if (!sprite.isTextureLoaded) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
// Create WebGL texture if not already created
|
|
157
|
+
if (!sprite.texture) {
|
|
158
|
+
sprite.createWebGLTexture(gl);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!sprite.texture) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Set blend mode
|
|
166
|
+
this._setBlendMode(sprite.blendMode);
|
|
167
|
+
|
|
168
|
+
// Bind texture
|
|
169
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
170
|
+
gl.bindTexture(gl.TEXTURE_2D, sprite.texture);
|
|
171
|
+
gl.uniform1i(this.locations.texture, 0);
|
|
172
|
+
|
|
173
|
+
// Set sprite-specific uniforms
|
|
174
|
+
const worldPos = sprite.getWorldPosition();
|
|
175
|
+
gl.uniform3fv(this.locations.spritePosition, worldPos.toArray());
|
|
176
|
+
gl.uniform2fv(this.locations.spriteSize, [sprite.width, sprite.height]);
|
|
177
|
+
gl.uniform1i(this.locations.isBillboard, sprite.isBillboard ? 1 : 0);
|
|
178
|
+
if (!sprite.isBillboard) {
|
|
179
|
+
gl.uniform3fv(this.locations.spriteForward, sprite.forward.toArray());
|
|
180
|
+
gl.uniform3fv(this.locations.spriteUp, sprite.up.toArray());
|
|
181
|
+
}
|
|
182
|
+
gl.uniform3fv(this.locations.color, sprite.color);
|
|
183
|
+
gl.uniform1f(this.locations.alpha, sprite.alpha);
|
|
184
|
+
|
|
185
|
+
// Draw the quad
|
|
186
|
+
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Restore depth writing
|
|
190
|
+
gl.depthMask(true);
|
|
191
|
+
|
|
192
|
+
// Restore normal blending
|
|
193
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
194
|
+
|
|
195
|
+
// Cleanup
|
|
196
|
+
gl.disableVertexAttribArray(this.locations.position);
|
|
197
|
+
gl.disableVertexAttribArray(this.locations.texCoord);
|
|
198
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
199
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
200
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Calculate camera right and up vectors for billboarding
|
|
205
|
+
* @param {Object} camera - Camera object
|
|
206
|
+
* @returns {Object} Object containing right and up vectors
|
|
207
|
+
* @private
|
|
208
|
+
*/
|
|
209
|
+
_calculateCameraVectors(camera) {
|
|
210
|
+
// Calculate view direction
|
|
211
|
+
const forward = camera.target.sub(camera.position).normalize();
|
|
212
|
+
|
|
213
|
+
// Calculate right vector (cross product of forward and world up)
|
|
214
|
+
const worldUp = new Vector3(0, 1, 0);
|
|
215
|
+
const right = forward.cross(worldUp).normalize();
|
|
216
|
+
|
|
217
|
+
// Calculate up vector (cross product of right and forward)
|
|
218
|
+
const up = right.cross(forward).normalize();
|
|
219
|
+
|
|
220
|
+
return { right, up };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Set OpenGL blend mode based on sprite blend mode
|
|
225
|
+
* @param {string} blendMode - Blend mode ('normal', 'additive', 'multiply')
|
|
226
|
+
* @private
|
|
227
|
+
*/
|
|
228
|
+
_setBlendMode(blendMode) {
|
|
229
|
+
const gl = this.gl;
|
|
230
|
+
|
|
231
|
+
switch (blendMode) {
|
|
232
|
+
case 'additive':
|
|
233
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
|
|
234
|
+
break;
|
|
235
|
+
case 'multiply':
|
|
236
|
+
gl.blendFunc(gl.DST_COLOR, gl.ZERO);
|
|
237
|
+
break;
|
|
238
|
+
case 'normal':
|
|
239
|
+
default:
|
|
240
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Cleanup WebGL resources
|
|
247
|
+
*/
|
|
248
|
+
dispose() {
|
|
249
|
+
const gl = this.gl;
|
|
250
|
+
|
|
251
|
+
if (this.quadBuffer) {
|
|
252
|
+
gl.deleteBuffer(this.quadBuffer);
|
|
253
|
+
this.quadBuffer = null;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (this.indexBuffer) {
|
|
257
|
+
gl.deleteBuffer(this.indexBuffer);
|
|
258
|
+
this.indexBuffer = null;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (this.program) {
|
|
262
|
+
gl.deleteProgram(this.program);
|
|
263
|
+
this.program = null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// actionengine/display/graphics/renderers/actionrenderer3D/sunrenderer3D.js
|
|
2
|
+
class SunRenderer3D {
|
|
3
|
+
constructor(gl, programManager) {
|
|
4
|
+
this.gl = gl;
|
|
5
|
+
this.programManager = programManager;
|
|
6
|
+
|
|
7
|
+
// Create shader program for the sun
|
|
8
|
+
this.createShaderProgram();
|
|
9
|
+
|
|
10
|
+
// Create sun point buffer
|
|
11
|
+
this.createSunBuffer();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
createShaderProgram() {
|
|
15
|
+
// Simple vertex shader with point size
|
|
16
|
+
const vsSource = `#version 300 es
|
|
17
|
+
in vec3 aPosition;
|
|
18
|
+
|
|
19
|
+
uniform mat4 uProjectionMatrix;
|
|
20
|
+
uniform mat4 uViewMatrix;
|
|
21
|
+
uniform float uPointSize;
|
|
22
|
+
|
|
23
|
+
void main() {
|
|
24
|
+
gl_Position = uProjectionMatrix * uViewMatrix * vec4(aPosition, 1.0);
|
|
25
|
+
gl_PointSize = uPointSize;
|
|
26
|
+
}`;
|
|
27
|
+
|
|
28
|
+
// Fragment shader with a circular point
|
|
29
|
+
const fsSource = `#version 300 es
|
|
30
|
+
precision mediump float;
|
|
31
|
+
|
|
32
|
+
uniform vec3 uSunColor;
|
|
33
|
+
out vec4 fragColor;
|
|
34
|
+
|
|
35
|
+
void main() {
|
|
36
|
+
// Calculate distance from center of point
|
|
37
|
+
vec2 coord = gl_PointCoord - vec2(0.5);
|
|
38
|
+
float distance = length(coord);
|
|
39
|
+
|
|
40
|
+
// Create a soft circle
|
|
41
|
+
float alpha = 1.0 - smoothstep(0.0, 0.5, distance);
|
|
42
|
+
|
|
43
|
+
// Sun color with alpha based on distance
|
|
44
|
+
fragColor = vec4(uSunColor, alpha);
|
|
45
|
+
}`;
|
|
46
|
+
|
|
47
|
+
// Create shader program
|
|
48
|
+
const vertexShader = this.compileShader(this.gl.VERTEX_SHADER, vsSource);
|
|
49
|
+
const fragmentShader = this.compileShader(this.gl.FRAGMENT_SHADER, fsSource);
|
|
50
|
+
|
|
51
|
+
this.program = this.gl.createProgram();
|
|
52
|
+
this.gl.attachShader(this.program, vertexShader);
|
|
53
|
+
this.gl.attachShader(this.program, fragmentShader);
|
|
54
|
+
this.gl.linkProgram(this.program);
|
|
55
|
+
|
|
56
|
+
if (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {
|
|
57
|
+
console.error('Unable to initialize sun shader program:', this.gl.getProgramInfoLog(this.program));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Get attribute and uniform locations
|
|
62
|
+
this.locations = {
|
|
63
|
+
position: this.gl.getAttribLocation(this.program, 'aPosition'),
|
|
64
|
+
projectionMatrix: this.gl.getUniformLocation(this.program, 'uProjectionMatrix'),
|
|
65
|
+
viewMatrix: this.gl.getUniformLocation(this.program, 'uViewMatrix'),
|
|
66
|
+
pointSize: this.gl.getUniformLocation(this.program, 'uPointSize'),
|
|
67
|
+
sunColor: this.gl.getUniformLocation(this.program, 'uSunColor')
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
compileShader(type, source) {
|
|
72
|
+
const shader = this.gl.createShader(type);
|
|
73
|
+
this.gl.shaderSource(shader, source);
|
|
74
|
+
this.gl.compileShader(shader);
|
|
75
|
+
|
|
76
|
+
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
77
|
+
console.error('Shader compile error:', this.gl.getShaderInfoLog(shader));
|
|
78
|
+
this.gl.deleteShader(shader);
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return shader;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
createSunBuffer() {
|
|
86
|
+
// Create a buffer for a single point
|
|
87
|
+
this.sunBuffer = this.gl.createBuffer();
|
|
88
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.sunBuffer);
|
|
89
|
+
|
|
90
|
+
// Just one point at origin, will be positioned later
|
|
91
|
+
const position = new Float32Array([0, 0, 0]);
|
|
92
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, position, this.gl.STATIC_DRAW);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
render(camera, lightPos, isVirtualBoyMode) {
|
|
96
|
+
const gl = this.gl;
|
|
97
|
+
|
|
98
|
+
// Use our sun shader program
|
|
99
|
+
gl.useProgram(this.program);
|
|
100
|
+
|
|
101
|
+
// Set matrices
|
|
102
|
+
const projectionMatrix = Matrix4.perspective(Matrix4.create(), camera.fov, Game.WIDTH / Game.HEIGHT, 0.1, 100000.0);
|
|
103
|
+
const viewMatrix = Matrix4.create();
|
|
104
|
+
Matrix4.lookAt(viewMatrix, camera.position.toArray(), camera.target.toArray(), camera.up.toArray());
|
|
105
|
+
|
|
106
|
+
gl.uniformMatrix4fv(this.locations.projectionMatrix, false, projectionMatrix);
|
|
107
|
+
gl.uniformMatrix4fv(this.locations.viewMatrix, false, viewMatrix);
|
|
108
|
+
|
|
109
|
+
// Set sun color based on active shader
|
|
110
|
+
if (isVirtualBoyMode) {
|
|
111
|
+
// Red for VirtualBoy shader variant
|
|
112
|
+
gl.uniform3f(this.locations.sunColor, 1.0, 0.0, 0.0);
|
|
113
|
+
} else {
|
|
114
|
+
// Default yellow-orange
|
|
115
|
+
gl.uniform3f(this.locations.sunColor, 1.0, 0.9, 0.5);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Set point size (5x smaller as requested)
|
|
119
|
+
gl.uniform1f(this.locations.pointSize, 100.0);
|
|
120
|
+
|
|
121
|
+
// Bind position buffer
|
|
122
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.sunBuffer);
|
|
123
|
+
gl.vertexAttribPointer(this.locations.position, 3, gl.FLOAT, false, 0, 0);
|
|
124
|
+
gl.enableVertexAttribArray(this.locations.position);
|
|
125
|
+
|
|
126
|
+
// Update the buffer with the sun position
|
|
127
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([lightPos.x, lightPos.y, lightPos.z]));
|
|
128
|
+
|
|
129
|
+
// Enable blending
|
|
130
|
+
gl.enable(gl.BLEND);
|
|
131
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
132
|
+
|
|
133
|
+
// Draw the sun as a point
|
|
134
|
+
gl.drawArrays(gl.POINTS, 0, 1);
|
|
135
|
+
|
|
136
|
+
// Clean up
|
|
137
|
+
gl.disable(gl.BLEND);
|
|
138
|
+
gl.disableVertexAttribArray(this.locations.position);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
class WaterRenderer3D {
|
|
2
|
+
constructor(gl, programManager) {
|
|
3
|
+
this.gl = gl;
|
|
4
|
+
this.programManager = programManager;
|
|
5
|
+
this.waterProgram = programManager.getWaterProgram();
|
|
6
|
+
this.waterLocations = programManager.getWaterLocations();
|
|
7
|
+
this.waterBuffers = {
|
|
8
|
+
position: gl.createBuffer(),
|
|
9
|
+
normal: gl.createBuffer(),
|
|
10
|
+
texCoord: gl.createBuffer(),
|
|
11
|
+
indices: gl.createBuffer()
|
|
12
|
+
};
|
|
13
|
+
this.waterIndexCount = 0;
|
|
14
|
+
|
|
15
|
+
// Add configuration options for water appearance
|
|
16
|
+
this.waterConfig = {
|
|
17
|
+
waveHeight: 2.0, // Increased from 0.5 to 2.0 to match shader
|
|
18
|
+
waveSpeed: 1.0,
|
|
19
|
+
transparency: 0.8,
|
|
20
|
+
reflectivity: 0.6,
|
|
21
|
+
waterColor: [0.0, 0.48, 0.71],
|
|
22
|
+
waveDensity: 2.0
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
this.initializeWaterMesh();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
initializeWaterMesh() {
|
|
29
|
+
// Create a more detailed water mesh grid
|
|
30
|
+
const gridSize = 32; // Increase detail level
|
|
31
|
+
const size = 100;
|
|
32
|
+
const vertices = [];
|
|
33
|
+
const normals = [];
|
|
34
|
+
const texCoords = [];
|
|
35
|
+
const indices = [];
|
|
36
|
+
|
|
37
|
+
// Generate grid mesh
|
|
38
|
+
for (let z = 0; z <= gridSize; z++) {
|
|
39
|
+
for (let x = 0; x <= gridSize; x++) {
|
|
40
|
+
const xPos = (x / gridSize * 2 - 1) * size;
|
|
41
|
+
const zPos = (z / gridSize * 2 - 1) * size;
|
|
42
|
+
|
|
43
|
+
vertices.push(xPos, 0, zPos);
|
|
44
|
+
normals.push(0, 1, 0);
|
|
45
|
+
texCoords.push(x / gridSize, z / gridSize);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Generate indices for triangle strips
|
|
50
|
+
for (let z = 0; z < gridSize; z++) {
|
|
51
|
+
for (let x = 0; x < gridSize; x++) {
|
|
52
|
+
const topLeft = z * (gridSize + 1) + x;
|
|
53
|
+
const topRight = topLeft + 1;
|
|
54
|
+
const bottomLeft = (z + 1) * (gridSize + 1) + x;
|
|
55
|
+
const bottomRight = bottomLeft + 1;
|
|
56
|
+
|
|
57
|
+
indices.push(topLeft, bottomLeft, topRight);
|
|
58
|
+
indices.push(topRight, bottomLeft, bottomRight);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.waterBuffers.position);
|
|
63
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(vertices), this.gl.STATIC_DRAW);
|
|
64
|
+
|
|
65
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.waterBuffers.normal);
|
|
66
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(normals), this.gl.STATIC_DRAW);
|
|
67
|
+
|
|
68
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.waterBuffers.texCoord);
|
|
69
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(texCoords), this.gl.STATIC_DRAW);
|
|
70
|
+
|
|
71
|
+
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.waterBuffers.indices);
|
|
72
|
+
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), this.gl.STATIC_DRAW);
|
|
73
|
+
|
|
74
|
+
this.waterIndexCount = indices.length;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
render(camera, currentTime, ocean) {
|
|
78
|
+
this.gl.useProgram(this.waterProgram);
|
|
79
|
+
|
|
80
|
+
// Enhanced depth and blending setup
|
|
81
|
+
this.gl.enable(this.gl.DEPTH_TEST);
|
|
82
|
+
this.gl.depthMask(false); // Changed to false for better transparency handling
|
|
83
|
+
this.gl.enable(this.gl.BLEND);
|
|
84
|
+
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
|
|
85
|
+
|
|
86
|
+
const projection = Matrix4.perspective(Matrix4.create(), camera.fov, Game.WIDTH / Game.HEIGHT, 0.1, 10000.0);
|
|
87
|
+
const view = Matrix4.create();
|
|
88
|
+
Matrix4.lookAt(view, camera.position.toArray(), camera.target.toArray(), camera.up.toArray());
|
|
89
|
+
const model = Matrix4.create();
|
|
90
|
+
|
|
91
|
+
// Update water simulation
|
|
92
|
+
this.updateBuffersWithOcean(ocean);
|
|
93
|
+
|
|
94
|
+
// Set uniforms
|
|
95
|
+
this.gl.uniformMatrix4fv(this.waterLocations.projectionMatrix, false, projection);
|
|
96
|
+
this.gl.uniformMatrix4fv(this.waterLocations.viewMatrix, false, view);
|
|
97
|
+
this.gl.uniformMatrix4fv(this.waterLocations.modelMatrix, false, model);
|
|
98
|
+
this.gl.uniform1f(this.waterLocations.time, currentTime * this.waterConfig.waveSpeed);
|
|
99
|
+
this.gl.uniform3fv(this.waterLocations.cameraPos, camera.position.toArray());
|
|
100
|
+
this.gl.uniform3fv(this.waterLocations.lightDir, [0.5, -1.0, 0.5]);
|
|
101
|
+
|
|
102
|
+
// Add new water configuration uniforms
|
|
103
|
+
this.gl.uniform1f(this.waterLocations.waveHeight, this.waterConfig.waveHeight);
|
|
104
|
+
this.gl.uniform1f(this.waterLocations.transparency, this.waterConfig.transparency);
|
|
105
|
+
this.gl.uniform1f(this.waterLocations.reflectivity, this.waterConfig.reflectivity);
|
|
106
|
+
this.gl.uniform3fv(this.waterLocations.waterColor, this.waterConfig.waterColor);
|
|
107
|
+
this.gl.uniform1f(this.waterLocations.waveDensity, this.waterConfig.waveDensity);
|
|
108
|
+
|
|
109
|
+
// Set up attributes
|
|
110
|
+
this.setupAttributes();
|
|
111
|
+
|
|
112
|
+
// Draw water
|
|
113
|
+
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.waterBuffers.indices);
|
|
114
|
+
this.gl.drawElements(this.gl.TRIANGLES, this.waterIndexCount, this.gl.UNSIGNED_SHORT, 0);
|
|
115
|
+
|
|
116
|
+
// Cleanup
|
|
117
|
+
this.gl.depthMask(true);
|
|
118
|
+
this.gl.disable(this.gl.BLEND);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
setupAttributes() {
|
|
122
|
+
// Helper method to set up vertex attributes
|
|
123
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.waterBuffers.position);
|
|
124
|
+
this.gl.vertexAttribPointer(this.waterLocations.position, 3, this.gl.FLOAT, false, 0, 0);
|
|
125
|
+
this.gl.enableVertexAttribArray(this.waterLocations.position);
|
|
126
|
+
|
|
127
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.waterBuffers.normal);
|
|
128
|
+
this.gl.vertexAttribPointer(this.waterLocations.normal, 3, this.gl.FLOAT, false, 0, 0);
|
|
129
|
+
this.gl.enableVertexAttribArray(this.waterLocations.normal);
|
|
130
|
+
|
|
131
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.waterBuffers.texCoord);
|
|
132
|
+
this.gl.vertexAttribPointer(this.waterLocations.texCoord, 2, this.gl.FLOAT, false, 0, 0);
|
|
133
|
+
this.gl.enableVertexAttribArray(this.waterLocations.texCoord);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
updateBuffersWithOcean(ocean) {
|
|
137
|
+
if (!ocean.triangles?.length) return;
|
|
138
|
+
|
|
139
|
+
const positions = new Float32Array(ocean.triangles.length * 9);
|
|
140
|
+
const normals = new Float32Array(ocean.triangles.length * 9);
|
|
141
|
+
const indices = new Uint16Array(ocean.triangles.length * 3);
|
|
142
|
+
|
|
143
|
+
ocean.triangles.forEach((triangle, i) => {
|
|
144
|
+
const baseIndex = i * 9;
|
|
145
|
+
for (let j = 0; j < 3; j++) {
|
|
146
|
+
// Add subtle wave movement
|
|
147
|
+
const offset = Math.sin(Date.now() * 0.001 + triangle.vertices[j].x * 0.1) * this.waterConfig.waveHeight;
|
|
148
|
+
|
|
149
|
+
positions[baseIndex + j*3] = triangle.vertices[j].x;
|
|
150
|
+
positions[baseIndex + j*3 + 1] = triangle.vertices[j].y + offset + ocean.body.position.y;
|
|
151
|
+
positions[baseIndex + j*3 + 2] = triangle.vertices[j].z;
|
|
152
|
+
|
|
153
|
+
normals[baseIndex + j*3] = triangle.normal.x;
|
|
154
|
+
normals[baseIndex + j*3 + 1] = triangle.normal.y;
|
|
155
|
+
normals[baseIndex + j*3 + 2] = triangle.normal.z;
|
|
156
|
+
|
|
157
|
+
indices[i*3 + j] = i*3 + j;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
this.waterIndexCount = indices.length;
|
|
162
|
+
|
|
163
|
+
// Use DYNAMIC_DRAW for constantly updating buffers
|
|
164
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.waterBuffers.position);
|
|
165
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.DYNAMIC_DRAW);
|
|
166
|
+
|
|
167
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.waterBuffers.normal);
|
|
168
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, normals, this.gl.DYNAMIC_DRAW);
|
|
169
|
+
|
|
170
|
+
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.waterBuffers.indices);
|
|
171
|
+
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, indices, this.gl.DYNAMIC_DRAW);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// actionengine/display/graphics/renderers/actionrenderer3D/weatherrenderer3D.js
|
|
2
|
+
class WeatherRenderer3D {
|
|
3
|
+
constructor(gl, programManager) {
|
|
4
|
+
this.gl = gl;
|
|
5
|
+
this.programManager = programManager;
|
|
6
|
+
|
|
7
|
+
// Get particle programs and locations
|
|
8
|
+
this.particleProgram = this.programManager.getParticleProgram();
|
|
9
|
+
this.particleLocations = this.programManager.getParticleLocations();
|
|
10
|
+
|
|
11
|
+
// Create buffers for particles
|
|
12
|
+
this.particleBuffers = {
|
|
13
|
+
position: this.gl.createBuffer(),
|
|
14
|
+
size: this.gl.createBuffer(),
|
|
15
|
+
color: this.gl.createBuffer()
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
render(weatherSystem, camera) {
|
|
20
|
+
if (!weatherSystem || !weatherSystem.particleEmitter) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const particles = weatherSystem.particleEmitter.getParticles();
|
|
25
|
+
if (particles.length === 0) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Update particle buffers
|
|
30
|
+
const positions = new Float32Array(particles.length * 3);
|
|
31
|
+
const sizes = new Float32Array(particles.length);
|
|
32
|
+
const colors = new Float32Array(particles.length * 4);
|
|
33
|
+
|
|
34
|
+
particles.forEach((particle, i) => {
|
|
35
|
+
positions[i * 3] = particle.position.x;
|
|
36
|
+
positions[i * 3 + 1] = particle.position.y;
|
|
37
|
+
positions[i * 3 + 2] = particle.position.z;
|
|
38
|
+
|
|
39
|
+
sizes[i] = particle.size;
|
|
40
|
+
|
|
41
|
+
// Assuming rain particles are bluish
|
|
42
|
+
colors[i * 4] = 0.7; // R
|
|
43
|
+
colors[i * 4 + 1] = 0.7; // G
|
|
44
|
+
colors[i * 4 + 2] = 1.0; // B
|
|
45
|
+
colors[i * 4 + 3] = particle.alpha; // A
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Set up WebGL state for particle rendering
|
|
49
|
+
this.gl.enable(this.gl.BLEND);
|
|
50
|
+
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
|
|
51
|
+
|
|
52
|
+
// Use particle shader
|
|
53
|
+
this.gl.useProgram(this.particleProgram);
|
|
54
|
+
|
|
55
|
+
// Set matrices
|
|
56
|
+
const projection = Matrix4.perspective(Matrix4.create(), camera.fov, Game.WIDTH / Game.HEIGHT, 0.1, 10000.0);
|
|
57
|
+
const view = Matrix4.create();
|
|
58
|
+
Matrix4.lookAt(view, camera.position.toArray(), camera.target.toArray(), camera.up.toArray());
|
|
59
|
+
|
|
60
|
+
this.gl.uniformMatrix4fv(this.particleLocations.projectionMatrix, false, projection);
|
|
61
|
+
this.gl.uniformMatrix4fv(this.particleLocations.viewMatrix, false, view);
|
|
62
|
+
|
|
63
|
+
// Update and bind position buffer
|
|
64
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.particleBuffers.position);
|
|
65
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.DYNAMIC_DRAW);
|
|
66
|
+
this.gl.vertexAttribPointer(this.particleLocations.position, 3, this.gl.FLOAT, false, 0, 0);
|
|
67
|
+
this.gl.enableVertexAttribArray(this.particleLocations.position);
|
|
68
|
+
|
|
69
|
+
// Update and bind size buffer
|
|
70
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.particleBuffers.size);
|
|
71
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, sizes, this.gl.DYNAMIC_DRAW);
|
|
72
|
+
this.gl.vertexAttribPointer(this.particleLocations.size, 1, this.gl.FLOAT, false, 0, 0);
|
|
73
|
+
this.gl.enableVertexAttribArray(this.particleLocations.size);
|
|
74
|
+
|
|
75
|
+
// Update and bind color buffer
|
|
76
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.particleBuffers.color);
|
|
77
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, colors, this.gl.DYNAMIC_DRAW);
|
|
78
|
+
this.gl.vertexAttribPointer(this.particleLocations.color, 4, this.gl.FLOAT, false, 0, 0);
|
|
79
|
+
this.gl.enableVertexAttribArray(this.particleLocations.color);
|
|
80
|
+
|
|
81
|
+
// Draw particles
|
|
82
|
+
this.gl.drawArrays(this.gl.POINTS, 0, particles.length);
|
|
83
|
+
|
|
84
|
+
// Cleanup
|
|
85
|
+
this.gl.disable(this.gl.BLEND);
|
|
86
|
+
}
|
|
87
|
+
}
|