particle overhaul. emitters!
Some checks reported errors
studiorailgun/Renderer/pipeline/head Something is wrong with the build of this commit
Some checks reported errors
studiorailgun/Renderer/pipeline/head Something is wrong with the build of this commit
This commit is contained in:
parent
63a302444f
commit
2ef4b13786
@ -7,6 +7,29 @@
|
|||||||
"tokens": [
|
"tokens": [
|
||||||
"SPAWNPOINT"
|
"SPAWNPOINT"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id" : "particleEmitterTest",
|
||||||
|
"particleEmitter": {
|
||||||
|
"maxLife": 40,
|
||||||
|
"lifeCurrent": 0,
|
||||||
|
"particleVelocity": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.1,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"acceleration": -0.01,
|
||||||
|
"texture": "",
|
||||||
|
"size": 0.3,
|
||||||
|
"color": {
|
||||||
|
"x": 0.5,
|
||||||
|
"y": 0.5,
|
||||||
|
"z": 0.5
|
||||||
|
},
|
||||||
|
"frequency": 1
|
||||||
|
},
|
||||||
|
"tokens": [
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|||||||
@ -4,7 +4,11 @@
|
|||||||
"name" : "blood",
|
"name" : "blood",
|
||||||
"maxLife" : 7,
|
"maxLife" : 7,
|
||||||
"lifeCurrent" : 0,
|
"lifeCurrent" : 0,
|
||||||
"velocity" : 0.3,
|
"velocity" : {
|
||||||
|
"x": 0.3,
|
||||||
|
"y": 0.3,
|
||||||
|
"z": 0.3
|
||||||
|
},
|
||||||
"acceleration" : -0.1,
|
"acceleration" : -0.1,
|
||||||
"size": 0.15,
|
"size": 0.15,
|
||||||
"texture" : "Textures/bloodsplat1.png"
|
"texture" : "Textures/bloodsplat1.png"
|
||||||
|
|||||||
297
assets/Shaders/entities/particle/particle.fs
Normal file
297
assets/Shaders/entities/particle/particle.fs
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
//foliage.fs
|
||||||
|
|
||||||
|
/**
|
||||||
|
Bind points for different SSBOs
|
||||||
|
*/
|
||||||
|
#define CLUSTER_SSBO_BIND_POINT 1
|
||||||
|
#define POINT_LIGHT_SSBO_BIND_POINT 2
|
||||||
|
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Maximum number of point lights
|
||||||
|
*/
|
||||||
|
#define MAX_POINT_LIGHTS 512
|
||||||
|
|
||||||
|
/**
|
||||||
|
Maximum number of lights per cluster
|
||||||
|
*/
|
||||||
|
#define MAX_LIGHTS_PER_CLUSTER 100
|
||||||
|
|
||||||
|
/**
|
||||||
|
The direct global light
|
||||||
|
*/
|
||||||
|
struct DirectLight {
|
||||||
|
vec3 direction;
|
||||||
|
vec3 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
A point light
|
||||||
|
*/
|
||||||
|
struct PointLight {
|
||||||
|
vec4 position;
|
||||||
|
vec4 color;
|
||||||
|
float constant;
|
||||||
|
float linear;
|
||||||
|
float quadratic;
|
||||||
|
float radius;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
A light cluster
|
||||||
|
*/
|
||||||
|
struct Cluster {
|
||||||
|
vec4 minPoint;
|
||||||
|
vec4 maxPoint;
|
||||||
|
uint count;
|
||||||
|
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||||
|
};
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
|
||||||
|
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||||
|
Cluster clusters[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||||
|
PointLight pointLight[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||||
|
DirectLight directLight;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Material {
|
||||||
|
sampler2D diffuse;
|
||||||
|
sampler2D specular;
|
||||||
|
float shininess;
|
||||||
|
};
|
||||||
|
|
||||||
|
in vec3 FragPos;
|
||||||
|
in vec3 ViewFragPos;
|
||||||
|
in vec3 Normal;
|
||||||
|
in vec2 TexCoord;
|
||||||
|
in vec4 FragPosLightSpace;
|
||||||
|
in vec4 color;
|
||||||
|
|
||||||
|
|
||||||
|
uniform vec3 viewPos;
|
||||||
|
// uniform DirLight dirLight;
|
||||||
|
// uniform PointLight pointLights[NR_POINT_LIGHTS];
|
||||||
|
// uniform SpotLight spotLight;
|
||||||
|
uniform Material material;
|
||||||
|
|
||||||
|
//texture stuff
|
||||||
|
// uniform sampler2D ourTexture;
|
||||||
|
uniform int hasTransparency;
|
||||||
|
// uniform sampler2D specularTexture;
|
||||||
|
|
||||||
|
//light depth map
|
||||||
|
uniform sampler2D shadowMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Used for light cluster calculation
|
||||||
|
*/
|
||||||
|
uniform float zNear;
|
||||||
|
uniform float zFar;
|
||||||
|
uniform uvec3 gridSize;
|
||||||
|
uniform uvec2 screenDimensions;
|
||||||
|
uniform mat4 view;
|
||||||
|
|
||||||
|
|
||||||
|
// function prototypes
|
||||||
|
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||||
|
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||||
|
float calcLightIntensityTotal(vec3 normal);
|
||||||
|
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||||
|
float easeIn(float interpolator);
|
||||||
|
float easeOut(float interpolator);
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
vec3 viewDir = normalize(viewPos - FragPos);
|
||||||
|
|
||||||
|
//grab light intensity
|
||||||
|
vec3 lightIntensity = vec3(calcLightIntensityTotal(Normal));
|
||||||
|
|
||||||
|
//get color of base texture
|
||||||
|
// vec3 textureColor = vec3((norm.x + 1) / 2.0, norm.y, 1.0 - (norm.x + 1) / 2.0);
|
||||||
|
vec3 textureColor = color.rgb;
|
||||||
|
// vec3 textureColor = vec3(0.17647,0.4,0.09411);//texture(material.diffuse, TexCoord).rgb;
|
||||||
|
|
||||||
|
//shadow
|
||||||
|
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), Normal);
|
||||||
|
|
||||||
|
//
|
||||||
|
//point light calculations
|
||||||
|
uint clusterIndex = findCluster(ViewFragPos, zNear, zFar);
|
||||||
|
uint pointLightCount = clusters[clusterIndex].count;
|
||||||
|
for(int i = 0; i < pointLightCount; i++){
|
||||||
|
uint pointLightIndex = clusters[clusterIndex].lightIndices[i];
|
||||||
|
PointLight pointLight = pointLight[pointLightIndex];
|
||||||
|
lightIntensity = lightIntensity + CalcPointLight(pointLight, Normal, FragPos, viewDir);
|
||||||
|
}
|
||||||
|
//error checking on light clusters
|
||||||
|
if(pointLightCount > MAX_LIGHTS_PER_CLUSTER){
|
||||||
|
FragColor = vec4(1.0f,0.0f,0.0f,1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculate final color
|
||||||
|
vec3 finalColor = textureColor * lightIntensity;// * max(shadow,0.4);
|
||||||
|
// vec3 lightAmount = CalcDirLight(norm, viewDir);
|
||||||
|
// for(int i = 0; i < NR_POINT_LIGHTS; i++){
|
||||||
|
// lightAmount += CalcPointLight(i, norm, FragPos, viewDir);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//this final calculation is for transparency
|
||||||
|
FragColor = vec4(finalColor, 1.0);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculates the color when using a directional light.
|
||||||
|
// vec3 CalcDirLight(vec3 normal, vec3 viewDir){
|
||||||
|
// vec3 lightDir = normalize(-dLDirection);
|
||||||
|
// // diffuse shading
|
||||||
|
// float diff = max(dot(normal, lightDir), 0.0);
|
||||||
|
// // specular shading
|
||||||
|
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||||
|
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||||
|
// // combine results
|
||||||
|
// vec3 texColor = texture(material.diffuse, TexCoord).rgb;
|
||||||
|
// vec3 diffuse = dLDiffuse * diff;
|
||||||
|
// //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
|
||||||
|
|
||||||
|
|
||||||
|
// float shadow = ShadowCalculation(FragPosLightSpace, lightDir, normal);
|
||||||
|
|
||||||
|
// return ( dLAmbient + (1.0-shadow) * diffuse ) * texColor;// + specular);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//
|
||||||
|
float calcLightIntensityAmbient(){
|
||||||
|
//calculate average of ambient light
|
||||||
|
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||||
|
return avg;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
float calcLightIntensityDir(vec3 normal){
|
||||||
|
vec3 lightDir = normalize(-directLight.direction);
|
||||||
|
// diffuse shading
|
||||||
|
float diff = max(dot(normal, lightDir), 0.0);
|
||||||
|
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
float calcLightIntensityTotal(vec3 normal){
|
||||||
|
//ambient intensity
|
||||||
|
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||||
|
|
||||||
|
//get direct intensity
|
||||||
|
float directLightIntensity = calcLightIntensityDir(normal);
|
||||||
|
|
||||||
|
//sum
|
||||||
|
float total = ambientLightIntensity + directLightIntensity;
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
vec3 getTotalLightColor(vec3 normal){
|
||||||
|
//get the direct light color adjusted for intensity
|
||||||
|
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||||
|
|
||||||
|
//sum light colors
|
||||||
|
vec3 totalLightColor = diffuseLightColor;
|
||||||
|
return totalLightColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||||
|
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||||
|
// diffuse shading
|
||||||
|
float diff = max(dot(normal, lightDir), 0.0);
|
||||||
|
// specular shading
|
||||||
|
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||||
|
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||||
|
// attenuation
|
||||||
|
float distance = length(pointLight.position.xyz - fragPos);
|
||||||
|
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||||
|
if(distance > pointLight.radius){
|
||||||
|
attenuation = 0;
|
||||||
|
}
|
||||||
|
// combine results
|
||||||
|
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||||
|
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||||
|
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||||
|
ambient = ambient * attenuation;
|
||||||
|
diffuse = diffuse * attenuation;
|
||||||
|
// specular *= attenuation;
|
||||||
|
vec3 specular = vec3(0,0,0);
|
||||||
|
|
||||||
|
vec3 finalValue = vec3(0);
|
||||||
|
if(distance < pointLight.radius){
|
||||||
|
finalValue = (ambient + diffuse + specular);
|
||||||
|
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Finds the light cluster this fragment belongs to
|
||||||
|
*/
|
||||||
|
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||||
|
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||||
|
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||||
|
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||||
|
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||||
|
|
||||||
|
// perform perspective divide
|
||||||
|
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||||
|
|
||||||
|
//transform to NDC
|
||||||
|
projCoords = projCoords * 0.5 + 0.5;
|
||||||
|
|
||||||
|
//get closest depth from light's POV
|
||||||
|
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||||
|
|
||||||
|
//get depth of current fragment
|
||||||
|
float currentDepth = projCoords.z;
|
||||||
|
|
||||||
|
//calculate bias
|
||||||
|
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||||
|
|
||||||
|
//calculate shadow value
|
||||||
|
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||||
|
|
||||||
|
if(projCoords.z > 1.0){
|
||||||
|
shadow = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||||
|
//ie the fragment is already facing away from the light source
|
||||||
|
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||||
|
|
||||||
|
if(dotprod > 0.0){
|
||||||
|
shadow = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// shadow = currentDepth;
|
||||||
|
|
||||||
|
return shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float easeIn(float interpolator){
|
||||||
|
return interpolator * interpolator;
|
||||||
|
}
|
||||||
|
|
||||||
|
float easeOut(float interpolator){
|
||||||
|
return 1 - easeIn(1 - interpolator);
|
||||||
|
}
|
||||||
76
assets/Shaders/entities/particle/particle.vs
Normal file
76
assets/Shaders/entities/particle/particle.vs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//Vertex Shader
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
/**
|
||||||
|
Bind points for different SSBOs
|
||||||
|
*/
|
||||||
|
#define PARTICLE_SSBO_BIND_POINT 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
A point light
|
||||||
|
*/
|
||||||
|
struct ParticleData {
|
||||||
|
mat4 model;
|
||||||
|
vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//input buffers
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec3 aNormal;
|
||||||
|
layout (location = 4) in vec2 aTex;
|
||||||
|
|
||||||
|
layout(std430, binding = PARTICLE_SSBO_BIND_POINT) restrict buffer particleSSBO {
|
||||||
|
ParticleData particleData[];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//coordinate space transformation matrices
|
||||||
|
uniform mat4 transform;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 lightSpaceMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//output buffers
|
||||||
|
out vec3 Normal;
|
||||||
|
out vec3 FragPos;
|
||||||
|
out vec3 ViewFragPos;
|
||||||
|
out vec2 TexCoord;
|
||||||
|
out vec4 FragPosLightSpace;
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
ParticleData currentData = particleData[gl_InstanceID];
|
||||||
|
|
||||||
|
mat4 model = currentData.model;
|
||||||
|
color = currentData.color;
|
||||||
|
|
||||||
|
//normalize posiiton and normal
|
||||||
|
vec4 FinalVertex = vec4(aPos, 1.0);
|
||||||
|
vec4 FinalNormal = vec4(aNormal, 1.0);
|
||||||
|
|
||||||
|
//make sure the W component is 1.0
|
||||||
|
FinalVertex = vec4(FinalVertex.xyz, 1.0);
|
||||||
|
FinalNormal = vec4(FinalNormal.xyz, 1.0);
|
||||||
|
|
||||||
|
|
||||||
|
//push frag, normal, and texture positions to fragment shader
|
||||||
|
FragPos = vec3(model * FinalVertex);
|
||||||
|
ViewFragPos = vec3(view * model * FinalVertex);
|
||||||
|
Normal = mat3(transpose(inverse(model))) * aNormal;
|
||||||
|
TexCoord = aTex;
|
||||||
|
|
||||||
|
|
||||||
|
//shadow map stuff
|
||||||
|
FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0);
|
||||||
|
|
||||||
|
|
||||||
|
//set final position with opengl space
|
||||||
|
gl_Position = projection * view * model * FinalVertex;
|
||||||
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
#maven.buildNumber.plugin properties file
|
#maven.buildNumber.plugin properties file
|
||||||
#Thu Sep 19 15:35:07 EDT 2024
|
#Thu Sep 19 21:21:28 EDT 2024
|
||||||
buildNumber=339
|
buildNumber=351
|
||||||
|
|||||||
@ -811,6 +811,7 @@ Fix terrain editing across chunk borders on server
|
|||||||
- This is because the ray on the client doesn't intersect at the border (because the physics generation isn't working on chunk-end)
|
- This is because the ray on the client doesn't intersect at the border (because the physics generation isn't working on chunk-end)
|
||||||
- Also because the client doesn't scan border chunks to see if they should update
|
- Also because the client doesn't scan border chunks to see if they should update
|
||||||
Fix shader program bug with no-bone variants
|
Fix shader program bug with no-bone variants
|
||||||
|
Particle Emitter work (it renders! it has management!)
|
||||||
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package electrosphere.client.entity.instance;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import electrosphere.renderer.actor.instance.StridedInstanceData;
|
||||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||||
|
|
||||||
@ -19,6 +20,16 @@ public class InstanceTemplate {
|
|||||||
//The map of all attributes for instanced foliage
|
//The map of all attributes for instanced foliage
|
||||||
protected Map<ShaderAttribute,HomogenousBufferTypes> attributes;
|
protected Map<ShaderAttribute,HomogenousBufferTypes> attributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The strided instance data
|
||||||
|
*/
|
||||||
|
protected StridedInstanceData stridedInstanceData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bind point for the data
|
||||||
|
*/
|
||||||
|
int dataBindPoint;
|
||||||
|
|
||||||
//shader paths
|
//shader paths
|
||||||
protected String vertexPath;
|
protected String vertexPath;
|
||||||
protected String fragmentPath;
|
protected String fragmentPath;
|
||||||
@ -42,6 +53,26 @@ public class InstanceTemplate {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a template to create instanced actors off of
|
||||||
|
* @param capacity The number of actors that can be drawn per frame (going over this limit will result in drawing the closest ${capacity} number of actors)
|
||||||
|
* @param modelPath The path for the model of the instance
|
||||||
|
* @param vertexPath The vertex shader path
|
||||||
|
* @param fragmentPath The fragment shader path
|
||||||
|
* @param stridedInstanceData The strided instance data to use
|
||||||
|
* @return The template
|
||||||
|
*/
|
||||||
|
public static InstanceTemplate createInstanceTemplate(int capacity, String modelPath, String vertexPath, String fragmentPath, StridedInstanceData stridedInstanceData, int bindPoint){
|
||||||
|
InstanceTemplate rVal = new InstanceTemplate();
|
||||||
|
rVal.capacity = capacity;
|
||||||
|
rVal.modelPath = modelPath;
|
||||||
|
rVal.vertexPath = vertexPath;
|
||||||
|
rVal.fragmentPath = fragmentPath;
|
||||||
|
rVal.stridedInstanceData = stridedInstanceData;
|
||||||
|
rVal.dataBindPoint = bindPoint;
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,12 +23,24 @@ public class InstancedEntityUtils {
|
|||||||
* @return The instanced actor that is attached to this entity
|
* @return The instanced actor that is attached to this entity
|
||||||
*/
|
*/
|
||||||
public static InstancedActor makeEntityInstanced(Entity entity, InstanceTemplate template){
|
public static InstancedActor makeEntityInstanced(Entity entity, InstanceTemplate template){
|
||||||
InstancedActor instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
InstancedActor instancedActor = null;
|
||||||
template.modelPath,
|
if(template.attributes != null){
|
||||||
template.vertexPath,
|
instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
||||||
template.fragmentPath,
|
template.modelPath,
|
||||||
template.attributes,
|
template.vertexPath,
|
||||||
template.capacity);
|
template.fragmentPath,
|
||||||
|
template.attributes,
|
||||||
|
template.capacity
|
||||||
|
);
|
||||||
|
} else if(template.stridedInstanceData != null) {
|
||||||
|
instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
||||||
|
template.modelPath,
|
||||||
|
template.vertexPath,
|
||||||
|
template.fragmentPath,
|
||||||
|
template.stridedInstanceData,
|
||||||
|
template.capacity
|
||||||
|
);
|
||||||
|
}
|
||||||
entity.putData(EntityDataStrings.INSTANCED_ACTOR, instancedActor);
|
entity.putData(EntityDataStrings.INSTANCED_ACTOR, instancedActor);
|
||||||
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
||||||
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
|
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
|
||||||
@ -50,12 +62,24 @@ public class InstancedEntityUtils {
|
|||||||
* @return The instanced actor that is attached to this entity
|
* @return The instanced actor that is attached to this entity
|
||||||
*/
|
*/
|
||||||
public static InstancedActor makeEntityInstancedWithModelTransform(Entity entity, InstanceTemplate template, ShaderAttribute modelTransformAttribute){
|
public static InstancedActor makeEntityInstancedWithModelTransform(Entity entity, InstanceTemplate template, ShaderAttribute modelTransformAttribute){
|
||||||
InstancedActor instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
InstancedActor instancedActor = null;
|
||||||
template.modelPath,
|
if(template.attributes != null){
|
||||||
template.vertexPath,
|
instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
||||||
template.fragmentPath,
|
template.modelPath,
|
||||||
template.attributes,
|
template.vertexPath,
|
||||||
template.capacity);
|
template.fragmentPath,
|
||||||
|
template.attributes,
|
||||||
|
template.capacity
|
||||||
|
);
|
||||||
|
} else if(template.stridedInstanceData != null) {
|
||||||
|
instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
||||||
|
template.modelPath,
|
||||||
|
template.vertexPath,
|
||||||
|
template.fragmentPath,
|
||||||
|
template.stridedInstanceData,
|
||||||
|
template.capacity
|
||||||
|
);
|
||||||
|
}
|
||||||
entity.putData(EntityDataStrings.INSTANCED_ACTOR, instancedActor);
|
entity.putData(EntityDataStrings.INSTANCED_ACTOR, instancedActor);
|
||||||
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
||||||
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
|
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
|
||||||
|
|||||||
@ -3,10 +3,21 @@ package electrosphere.client.entity.particle;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
|
import electrosphere.client.entity.instance.InstanceTemplate;
|
||||||
|
import electrosphere.client.entity.instance.InstancedEntityUtils;
|
||||||
|
import electrosphere.engine.assetmanager.AssetDataStrings;
|
||||||
import electrosphere.engine.signal.Signal;
|
import electrosphere.engine.signal.Signal;
|
||||||
import electrosphere.engine.signal.SignalServiceImpl;
|
import electrosphere.engine.signal.SignalServiceImpl;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.EntityCreationUtils;
|
||||||
|
import electrosphere.entity.EntityUtils;
|
||||||
|
import electrosphere.entity.state.client.particle.ClientParticleTree;
|
||||||
|
import electrosphere.game.data.particle.ParticleData;
|
||||||
import electrosphere.renderer.actor.instance.StridedInstanceData;
|
import electrosphere.renderer.actor.instance.StridedInstanceData;
|
||||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||||
|
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The particle service
|
* The particle service
|
||||||
@ -18,16 +29,20 @@ public class ParticleService extends SignalServiceImpl {
|
|||||||
*/
|
*/
|
||||||
static final int MAX_PARTICLES = 1000;
|
static final int MAX_PARTICLES = 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bind point for the particle ssbo
|
||||||
|
*/
|
||||||
|
static final int PARTICLE_SSBO_BIND_POINT = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path to the vertex shader
|
* Path to the vertex shader
|
||||||
*/
|
*/
|
||||||
static final String VERTEX_SHADER_PATH = "";
|
static final String VERTEX_SHADER_PATH = "Shaders/entities/particle/particle.vs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path to the fragment shader
|
* Path to the fragment shader
|
||||||
*/
|
*/
|
||||||
static final String FRAGMENT_SHADER_PATH = "";
|
static final String FRAGMENT_SHADER_PATH = "Shaders/entities/particle/particle.fs";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,6 +50,16 @@ public class ParticleService extends SignalServiceImpl {
|
|||||||
*/
|
*/
|
||||||
StridedInstanceData particleInstanceData;
|
StridedInstanceData particleInstanceData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The template to use when creating instanced actors
|
||||||
|
*/
|
||||||
|
InstanceTemplate instanceTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
ShaderAttribute modelAttrib;
|
||||||
|
|
||||||
|
ShaderAttribute colorAttrib;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
@ -55,17 +80,14 @@ public class ParticleService extends SignalServiceImpl {
|
|||||||
boolean rVal = false;
|
boolean rVal = false;
|
||||||
switch(signal.getType()){
|
switch(signal.getType()){
|
||||||
case RENDERING_ENGINE_READY: {
|
case RENDERING_ENGINE_READY: {
|
||||||
List<HomogenousBufferTypes> types = Arrays.asList(new HomogenousBufferTypes[]{
|
modelAttrib = new ShaderAttribute("model", HomogenousBufferTypes.MAT4F);
|
||||||
//position
|
colorAttrib = new ShaderAttribute("color", HomogenousBufferTypes.VEC4F);
|
||||||
HomogenousBufferTypes.VEC3D,
|
List<ShaderAttribute> types = Arrays.asList(new ShaderAttribute[]{
|
||||||
//rotation
|
modelAttrib,
|
||||||
HomogenousBufferTypes.VEC4D,
|
colorAttrib,
|
||||||
//scale
|
|
||||||
HomogenousBufferTypes.VEC3D,
|
|
||||||
//texture index
|
|
||||||
HomogenousBufferTypes.INT,
|
|
||||||
});
|
});
|
||||||
this.particleInstanceData = new StridedInstanceData(MAX_PARTICLES,types,VERTEX_SHADER_PATH,FRAGMENT_SHADER_PATH);
|
this.particleInstanceData = new StridedInstanceData(MAX_PARTICLES,PARTICLE_SSBO_BIND_POINT,types,VERTEX_SHADER_PATH,FRAGMENT_SHADER_PATH);
|
||||||
|
this.instanceTemplate = InstanceTemplate.createInstanceTemplate(MAX_PARTICLES, AssetDataStrings.MODEL_PARTICLE, VERTEX_SHADER_PATH, FRAGMENT_SHADER_PATH, particleInstanceData, PARTICLE_SSBO_BIND_POINT);
|
||||||
rVal = true;
|
rVal = true;
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
@ -74,4 +96,34 @@ public class ParticleService extends SignalServiceImpl {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the instance data for the particles
|
||||||
|
* @return The instance data
|
||||||
|
*/
|
||||||
|
public StridedInstanceData getInstanceData(){
|
||||||
|
return this.particleInstanceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns a particle
|
||||||
|
* @param data The particle data for the particle
|
||||||
|
* @param position The position of the particle
|
||||||
|
* @return The particle
|
||||||
|
*/
|
||||||
|
public Entity spawn(ParticleData data, Vector3d position){
|
||||||
|
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||||
|
InstancedEntityUtils.makeEntityInstanced(rVal, instanceTemplate);
|
||||||
|
EntityUtils.getPosition(rVal).set(position);
|
||||||
|
ClientParticleTree.attachTree(rVal, data);
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShaderAttribute getModelAttrib(){
|
||||||
|
return modelAttrib;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShaderAttribute getColorAttrib(){
|
||||||
|
return colorAttrib;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
package electrosphere.client.entity.particle;
|
package electrosphere.client.entity.particle;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.engine.assetmanager.AssetDataStrings;
|
||||||
import electrosphere.entity.DrawableUtils;
|
import electrosphere.entity.DrawableUtils;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.EntityCreationUtils;
|
import electrosphere.entity.EntityCreationUtils;
|
||||||
import electrosphere.entity.EntityDataStrings;
|
import electrosphere.entity.EntityDataStrings;
|
||||||
import electrosphere.entity.EntityTags;
|
import electrosphere.entity.EntityTags;
|
||||||
import electrosphere.entity.EntityUtils;
|
import electrosphere.entity.EntityUtils;
|
||||||
import electrosphere.entity.state.ParticleTree;
|
import electrosphere.entity.state.client.particle.ClientParticleTree;
|
||||||
import electrosphere.entity.state.particle.ClientParticleTree;
|
|
||||||
import electrosphere.game.data.particle.ParticleData;
|
import electrosphere.game.data.particle.ParticleData;
|
||||||
import electrosphere.renderer.actor.Actor;
|
import electrosphere.renderer.actor.Actor;
|
||||||
import electrosphere.renderer.actor.ActorTextureMask;
|
import electrosphere.renderer.actor.ActorTextureMask;
|
||||||
@ -16,7 +16,6 @@ import electrosphere.renderer.actor.ActorTextureMask;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
import org.joml.Vector3f;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Particle utility functions
|
* Particle utility functions
|
||||||
@ -27,15 +26,15 @@ public class ParticleUtils {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static Entity clientSpawnStaticBillboardParticle(){
|
// public static Entity clientSpawnStaticBillboardParticle(){
|
||||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
// Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||||
EntityCreationUtils.makeEntityDrawable(rVal, Globals.particleBillboardModel);
|
// EntityCreationUtils.makeEntityDrawable(rVal, Globals.particleBillboardModel);
|
||||||
ParticleTree particleTree = new ParticleTree(rVal, 10, new Vector3f(0,0,0), 0, 0, false);
|
// ClientParticleTree particleTree = new ClientParticleTree(rVal, 10, new Vector3f(0,0,0), 0, 0, false);
|
||||||
rVal.putData(EntityDataStrings.TREE_CLIENTPARTICLETREE, particleTree);
|
// rVal.putData(EntityDataStrings.TREE_CLIENTPARTICLETREE, particleTree);
|
||||||
rVal.putData(EntityDataStrings.IS_PARTICLE, true);
|
// rVal.putData(EntityDataStrings.IS_PARTICLE, true);
|
||||||
Globals.clientSceneWrapper.getScene().registerEntityToTag(rVal, EntityTags.PARTICLE);
|
// Globals.clientSceneWrapper.getScene().registerEntityToTag(rVal, EntityTags.PARTICLE);
|
||||||
return rVal;
|
// return rVal;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawns a billboard particle
|
* Spawns a billboard particle
|
||||||
@ -45,7 +44,7 @@ public class ParticleUtils {
|
|||||||
*/
|
*/
|
||||||
public static Entity clientSpawnBillboardParticle(ParticleData data, Vector3d destination){
|
public static Entity clientSpawnBillboardParticle(ParticleData data, Vector3d destination){
|
||||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||||
EntityCreationUtils.makeEntityDrawable(rVal, Globals.particleBillboardModel);
|
EntityCreationUtils.makeEntityDrawable(rVal, AssetDataStrings.MODEL_PARTICLE);
|
||||||
|
|
||||||
//actor logic
|
//actor logic
|
||||||
Actor particleActor = EntityUtils.getActor(rVal);
|
Actor particleActor = EntityUtils.getActor(rVal);
|
||||||
|
|||||||
@ -76,6 +76,7 @@ public class ClientSimulation {
|
|||||||
//
|
//
|
||||||
//update attached entity positions
|
//update attached entity positions
|
||||||
AttachUtils.clientUpdateAttachedEntityPositions();
|
AttachUtils.clientUpdateAttachedEntityPositions();
|
||||||
|
Globals.particleService.handleAllSignals();
|
||||||
//
|
//
|
||||||
//Hitbox stuff
|
//Hitbox stuff
|
||||||
Globals.profiler.beginCpuSample("update hitboxes");
|
Globals.profiler.beginCpuSample("update hitboxes");
|
||||||
|
|||||||
@ -292,7 +292,6 @@ public class Globals {
|
|||||||
//
|
//
|
||||||
// Particle stuff
|
// Particle stuff
|
||||||
//
|
//
|
||||||
public static String particleBillboardModel;
|
|
||||||
public static ParticleDefinition particleDefinition;
|
public static ParticleDefinition particleDefinition;
|
||||||
public static ParticleService particleService;
|
public static ParticleService particleService;
|
||||||
|
|
||||||
@ -619,7 +618,7 @@ public class Globals {
|
|||||||
fontManager.loadFonts();
|
fontManager.loadFonts();
|
||||||
assetManager.registerModelToSpecificString(RenderUtils.createBitmapCharacter(), AssetDataStrings.BITMAP_CHARACTER_MODEL);
|
assetManager.registerModelToSpecificString(RenderUtils.createBitmapCharacter(), AssetDataStrings.BITMAP_CHARACTER_MODEL);
|
||||||
//particle billboard model
|
//particle billboard model
|
||||||
particleBillboardModel = assetManager.registerModel(RenderUtils.createParticleModel());
|
assetManager.registerModelToSpecificString(RenderUtils.createParticleModel(), AssetDataStrings.MODEL_PARTICLE);
|
||||||
//initialize required windows
|
//initialize required windows
|
||||||
WindowUtils.initBaseWindows();
|
WindowUtils.initBaseWindows();
|
||||||
//init default shaderProgram
|
//init default shaderProgram
|
||||||
|
|||||||
@ -15,6 +15,7 @@ public class AssetDataStrings {
|
|||||||
public static final String UNITSPHERE = "unitSphere";
|
public static final String UNITSPHERE = "unitSphere";
|
||||||
public static final String UNITCYLINDER = "unitCylinder";
|
public static final String UNITCYLINDER = "unitCylinder";
|
||||||
public static final String UNITCUBE = "unitCube";
|
public static final String UNITCUBE = "unitCube";
|
||||||
|
public static final String MODEL_PARTICLE = "particle";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI generic audio
|
* UI generic audio
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package electrosphere.entity;
|
|||||||
import org.joml.Quaterniond;
|
import org.joml.Quaterniond;
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.types.collision.CollisionObjUtils;
|
import electrosphere.entity.types.collision.CollisionObjUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,6 +29,7 @@ public class ClientEntityUtils {
|
|||||||
*/
|
*/
|
||||||
public static void destroyEntity(Entity entity){
|
public static void destroyEntity(Entity entity){
|
||||||
//check for client-specific stuff
|
//check for client-specific stuff
|
||||||
|
Globals.renderingEngine.getLightManager().destroyPointLight(entity);
|
||||||
|
|
||||||
//deregister all behavior trees
|
//deregister all behavior trees
|
||||||
EntityUtils.cleanUpEntity(entity);
|
EntityUtils.cleanUpEntity(entity);
|
||||||
|
|||||||
@ -260,9 +260,10 @@ public class EntityDataStrings {
|
|||||||
public static final String TREE_SERVEREQUIPSTATE = "treeServerEquipState";
|
public static final String TREE_SERVEREQUIPSTATE = "treeServerEquipState";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Light state
|
Client-only components
|
||||||
*/
|
*/
|
||||||
public static final String TREE_CLIENTLIGHTSTATE = "treeClientLightState";
|
public static final String TREE_CLIENTLIGHTSTATE = "treeClientLightState";
|
||||||
|
public static final String TREE_CLIENTPARTICLEEMITTERSTATE = "treeClientParticleEmitterState";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Inventory in general
|
Inventory in general
|
||||||
|
|||||||
@ -1,68 +0,0 @@
|
|||||||
package electrosphere.entity.state;
|
|
||||||
|
|
||||||
import electrosphere.entity.Entity;
|
|
||||||
import electrosphere.entity.EntityUtils;
|
|
||||||
import electrosphere.entity.btree.BehaviorTree;
|
|
||||||
|
|
||||||
import org.joml.Vector3d;
|
|
||||||
import org.joml.Vector3f;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Particle b tree
|
|
||||||
*/
|
|
||||||
public class ParticleTree implements BehaviorTree {
|
|
||||||
Entity parent;
|
|
||||||
boolean hasLife = true;
|
|
||||||
int maxLife;
|
|
||||||
int lifeCurrent;
|
|
||||||
Vector3f destination;
|
|
||||||
float velocity;
|
|
||||||
float acceleration;
|
|
||||||
|
|
||||||
public ParticleTree(Entity parent, int maxLife, Vector3f destination, float velocity, float acceleration, boolean hasLife){
|
|
||||||
this.parent = parent;
|
|
||||||
this.maxLife = maxLife;
|
|
||||||
this.destination = destination;
|
|
||||||
this.velocity = velocity;
|
|
||||||
this.acceleration = acceleration;
|
|
||||||
this.hasLife = hasLife;
|
|
||||||
lifeCurrent = maxLife;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMaxLife() {
|
|
||||||
return maxLife;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLifeCurrent() {
|
|
||||||
return lifeCurrent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector3f getDestination() {
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getVelocity() {
|
|
||||||
return velocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getAcceleration() {
|
|
||||||
return acceleration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void simulate(float deltaTime){
|
|
||||||
Vector3d parentPosition = EntityUtils.getPosition(parent);
|
|
||||||
parentPosition.add(new Vector3f(destination).mul(velocity));
|
|
||||||
velocity = velocity - acceleration;
|
|
||||||
if(velocity < 0){
|
|
||||||
velocity = 0;
|
|
||||||
acceleration = 0;
|
|
||||||
}
|
|
||||||
if(hasLife){
|
|
||||||
lifeCurrent--;
|
|
||||||
if(lifeCurrent <= 0){
|
|
||||||
EntityUtils.cleanUpEntity(parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,107 @@
|
|||||||
|
package electrosphere.entity.state.client.particle;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.EntityDataStrings;
|
||||||
|
import electrosphere.entity.EntityUtils;
|
||||||
|
import electrosphere.entity.btree.BehaviorTree;
|
||||||
|
import electrosphere.entity.state.equip.ClientEquipState;
|
||||||
|
import electrosphere.game.data.particle.ParticleData;
|
||||||
|
import electrosphere.game.data.particle.ParticleEmitter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A component that causes the entity to emit particles
|
||||||
|
*/
|
||||||
|
public class ClientParticleEmitterComponent implements BehaviorTree {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parent entity
|
||||||
|
*/
|
||||||
|
Entity parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The particle emitter data
|
||||||
|
*/
|
||||||
|
ParticleEmitter particleEmitter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last frame this emitter sent out a particle
|
||||||
|
*/
|
||||||
|
long lastEmittedFrame = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simulate(float deltaTime) {
|
||||||
|
Vector3d entityPos = EntityUtils.getPosition(parent);
|
||||||
|
if((float)(Globals.timekeeper.getNumberOfRenderFramesElapsed() - lastEmittedFrame) > particleEmitter.getFrequency()){
|
||||||
|
lastEmittedFrame = Globals.timekeeper.getNumberOfRenderFramesElapsed();
|
||||||
|
//create particle here
|
||||||
|
Globals.particleService.spawn(this.getData(), new Vector3d(entityPos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor
|
||||||
|
* @param parent
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
private ClientParticleEmitterComponent(Entity parent, Object ... params){
|
||||||
|
this.parent = parent;
|
||||||
|
particleEmitter = (ParticleEmitter)params[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets particle data for a new particle
|
||||||
|
* @return The data
|
||||||
|
*/
|
||||||
|
private ParticleData getData(){
|
||||||
|
ParticleData data = new ParticleData();
|
||||||
|
data.setAcceleration(this.particleEmitter.getAcceleration());
|
||||||
|
data.setColor(this.particleEmitter.getColor());
|
||||||
|
data.setLifeCurrent(this.particleEmitter.getLifeCurrent());
|
||||||
|
data.setMaxLife(this.particleEmitter.getMaxLife());
|
||||||
|
data.setSize(this.particleEmitter.getSize());
|
||||||
|
data.setTexture(this.particleEmitter.getTexture());
|
||||||
|
data.setVelocity(this.particleEmitter.getParticleVelocity());
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Attaches this tree to the entity.
|
||||||
|
* </p>
|
||||||
|
* @param entity The entity to attach to
|
||||||
|
* @param tree The behavior tree to attach
|
||||||
|
* @param params Optional parameters that will be provided to the constructor
|
||||||
|
*/
|
||||||
|
public static ClientParticleEmitterComponent attachTree(Entity parent, Object ... params){
|
||||||
|
ClientParticleEmitterComponent rVal = new ClientParticleEmitterComponent(parent,params);
|
||||||
|
//!!WARNING!! from here below should not be touched
|
||||||
|
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
|
||||||
|
parent.putData(EntityDataStrings.TREE_CLIENTPARTICLEEMITTERSTATE, rVal);
|
||||||
|
Globals.clientSceneWrapper.getScene().registerBehaviorTree(rVal);
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Detatches this tree from the entity.
|
||||||
|
* </p>
|
||||||
|
* @param entity The entity to detach to
|
||||||
|
* @param tree The behavior tree to detach
|
||||||
|
*/
|
||||||
|
public static void detachTree(Entity entity, BehaviorTree tree){
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Gets the ClientEquipState of the entity
|
||||||
|
* </p>
|
||||||
|
* @param entity the entity
|
||||||
|
* @return The ClientEquipState
|
||||||
|
*/
|
||||||
|
public static ClientEquipState getClientEquipState(Entity entity){
|
||||||
|
return (ClientEquipState)entity.getData(EntityDataStrings.TREE_CLIENTPARTICLEEMITTERSTATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,15 @@
|
|||||||
package electrosphere.entity.state.particle;
|
package electrosphere.entity.state.client.particle;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import org.joml.AxisAngle4f;
|
import org.joml.AxisAngle4f;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.joml.Quaternionf;
|
import org.joml.Quaternionf;
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
|
import electrosphere.client.entity.camera.CameraEntityUtils;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.ClientEntityUtils;
|
import electrosphere.entity.ClientEntityUtils;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
@ -12,6 +17,7 @@ import electrosphere.entity.EntityDataStrings;
|
|||||||
import electrosphere.entity.EntityUtils;
|
import electrosphere.entity.EntityUtils;
|
||||||
import electrosphere.entity.btree.BehaviorTree;
|
import electrosphere.entity.btree.BehaviorTree;
|
||||||
import electrosphere.game.data.particle.ParticleData;
|
import electrosphere.game.data.particle.ParticleData;
|
||||||
|
import electrosphere.renderer.actor.instance.InstancedActor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Particle component for a client-side particle
|
* Particle component for a client-side particle
|
||||||
@ -28,16 +34,22 @@ public class ClientParticleTree implements BehaviorTree {
|
|||||||
//current life
|
//current life
|
||||||
int lifeCurrent;
|
int lifeCurrent;
|
||||||
|
|
||||||
|
|
||||||
//The destination of the particle
|
|
||||||
Vector3d destination;
|
|
||||||
|
|
||||||
//the velocity of the particle
|
//the velocity of the particle
|
||||||
float velocity;
|
Vector3d velocity;
|
||||||
|
|
||||||
//the acceleration of the particle
|
//the acceleration of the particle
|
||||||
float acceleration;
|
float acceleration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data for this particle
|
||||||
|
*/
|
||||||
|
ParticleData particleData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color of the particle
|
||||||
|
*/
|
||||||
|
Vector3d color;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -48,20 +60,16 @@ public class ClientParticleTree implements BehaviorTree {
|
|||||||
if(params.length < 1){
|
if(params.length < 1){
|
||||||
throw new IllegalArgumentException("No particle data was provided");
|
throw new IllegalArgumentException("No particle data was provided");
|
||||||
}
|
}
|
||||||
if(params.length < 2){
|
this.particleData = (ParticleData)params[0];
|
||||||
throw new IllegalArgumentException("No destination set for the particle");
|
|
||||||
}
|
|
||||||
ParticleData particleData = (ParticleData)params[0];
|
|
||||||
Vector3d destination = (Vector3d)params[1];
|
|
||||||
|
|
||||||
//sets data for the tree
|
//sets data for the tree
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.maxLife = particleData.getMaxLife();
|
this.maxLife = particleData.getMaxLife();
|
||||||
this.destination = destination;
|
|
||||||
this.velocity = particleData.getVelocity();
|
this.velocity = particleData.getVelocity();
|
||||||
this.acceleration = particleData.getAcceleration();
|
this.acceleration = particleData.getAcceleration();
|
||||||
this.hasLife = particleData.getMaxLife() != null;
|
this.hasLife = particleData.getMaxLife() != null;
|
||||||
this.lifeCurrent = maxLife;
|
this.lifeCurrent = maxLife;
|
||||||
|
this.color = new Vector3d(new Random().nextFloat(),new Random().nextFloat(),new Random().nextFloat());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxLife() {
|
public int getMaxLife() {
|
||||||
@ -72,11 +80,7 @@ public class ClientParticleTree implements BehaviorTree {
|
|||||||
return lifeCurrent;
|
return lifeCurrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3d getDestination() {
|
public Vector3d getVelocity() {
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getVelocity() {
|
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,17 +90,25 @@ public class ClientParticleTree implements BehaviorTree {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void simulate(float deltaTime){
|
public void simulate(float deltaTime){
|
||||||
|
InstancedActor instancedActor = InstancedActor.getInstancedActor(parent);
|
||||||
Vector3d parentPosition = EntityUtils.getPosition(parent);
|
Vector3d parentPosition = EntityUtils.getPosition(parent);
|
||||||
parentPosition.add(new Vector3d(destination).mul(velocity));
|
Vector3f cameraPos = CameraEntityUtils.getCameraCenter(Globals.playerCamera);
|
||||||
velocity = velocity + acceleration;
|
|
||||||
if(velocity < 0){
|
//update position
|
||||||
velocity = 0;
|
parentPosition.set(new Vector3d(parentPosition).add(velocity));
|
||||||
|
|
||||||
|
//update velocity
|
||||||
|
Vector3d accelerationVec = new Vector3d(velocity).normalize().mul(acceleration);
|
||||||
|
velocity = new Vector3d(velocity).add(accelerationVec);
|
||||||
|
if(velocity.length() < 0){
|
||||||
|
velocity = new Vector3d(0,0,0);
|
||||||
acceleration = 0;
|
acceleration = 0;
|
||||||
}
|
}
|
||||||
if(hasLife){
|
if(hasLife){
|
||||||
lifeCurrent--;
|
lifeCurrent--;
|
||||||
if(lifeCurrent <= 0){
|
if(lifeCurrent <= 0){
|
||||||
ClientEntityUtils.destroyEntity(parent);
|
ClientEntityUtils.destroyEntity(parent);
|
||||||
|
Globals.clientSceneWrapper.getScene().deregisterBehaviorTree(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +116,19 @@ public class ClientParticleTree implements BehaviorTree {
|
|||||||
Matrix4f rotationMatrix = new Matrix4f(Globals.viewMatrix).invert();
|
Matrix4f rotationMatrix = new Matrix4f(Globals.viewMatrix).invert();
|
||||||
Quaternionf rotation = new Quaternionf(rotationMatrix.getRotation(new AxisAngle4f()));
|
Quaternionf rotation = new Quaternionf(rotationMatrix.getRotation(new AxisAngle4f()));
|
||||||
EntityUtils.getRotation(parent).set(rotation);
|
EntityUtils.getRotation(parent).set(rotation);
|
||||||
|
|
||||||
|
Vector3f scale = EntityUtils.getScale(parent);
|
||||||
|
scale.set(this.particleData.getSize());
|
||||||
|
|
||||||
|
//push values to buffer that eventually gets uploaded to gpu
|
||||||
|
if(instancedActor != null){
|
||||||
|
instancedActor.setAttribute(Globals.particleService.getModelAttrib(), new Matrix4f().translationRotateScale(
|
||||||
|
new Vector3f((float)parentPosition.x,(float)parentPosition.y,(float)parentPosition.z).sub(cameraPos),
|
||||||
|
new Quaternionf(rotation),
|
||||||
|
scale
|
||||||
|
));
|
||||||
|
instancedActor.setAttribute(Globals.particleService.getColorAttrib(), new Vector4f((float)this.color.x,(float)this.color.y,(float)this.color.z,1.0f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,7 +84,7 @@ public class ClientPointLightComponent implements BehaviorTree {
|
|||||||
* @return The ClientEquipState
|
* @return The ClientEquipState
|
||||||
*/
|
*/
|
||||||
public static ClientEquipState getClientEquipState(Entity entity){
|
public static ClientEquipState getClientEquipState(Entity entity){
|
||||||
return (ClientEquipState)entity.getData(EntityDataStrings.TREE_CLIENTEQUIPSTATE);
|
return (ClientEquipState)entity.getData(EntityDataStrings.TREE_CLIENTLIGHTSTATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import electrosphere.entity.state.attack.ServerAttackTree;
|
|||||||
import electrosphere.entity.state.attack.ShooterTree;
|
import electrosphere.entity.state.attack.ShooterTree;
|
||||||
import electrosphere.entity.state.block.ClientBlockTree;
|
import electrosphere.entity.state.block.ClientBlockTree;
|
||||||
import electrosphere.entity.state.block.ServerBlockTree;
|
import electrosphere.entity.state.block.ServerBlockTree;
|
||||||
|
import electrosphere.entity.state.client.particle.ClientParticleEmitterComponent;
|
||||||
import electrosphere.entity.state.equip.ClientEquipState;
|
import electrosphere.entity.state.equip.ClientEquipState;
|
||||||
import electrosphere.entity.state.equip.ServerEquipState;
|
import electrosphere.entity.state.equip.ServerEquipState;
|
||||||
import electrosphere.entity.state.gravity.ClientGravityTree;
|
import electrosphere.entity.state.gravity.ClientGravityTree;
|
||||||
@ -257,6 +258,15 @@ public class CommonEntityUtils {
|
|||||||
ClientPointLightComponent.attachTree(entity, rawType.getPointLight());
|
ClientPointLightComponent.attachTree(entity, rawType.getPointLight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Particle emitter
|
||||||
|
//
|
||||||
|
//
|
||||||
|
if(rawType.getParticleEmitter() != null){
|
||||||
|
ClientParticleEmitterComponent.attachTree(entity, rawType.getParticleEmitter());
|
||||||
|
}
|
||||||
|
|
||||||
if(rawType.getEquipPoints() != null && rawType.getEquipPoints().size() > 0){
|
if(rawType.getEquipPoints() != null && rawType.getEquipPoints().size() > 0){
|
||||||
ClientEquipState.attachTree(entity, rawType.getEquipPoints());
|
ClientEquipState.attachTree(entity, rawType.getEquipPoints());
|
||||||
entity.putData(EntityDataStrings.EQUIP_INVENTORY, RelationalInventoryState.buildRelationalInventoryStateFromEquipList(rawType.getEquipPoints()));
|
entity.putData(EntityDataStrings.EQUIP_INVENTORY, RelationalInventoryState.buildRelationalInventoryStateFromEquipList(rawType.getEquipPoints()));
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import electrosphere.game.data.foliage.type.AmbientAudio;
|
|||||||
import electrosphere.game.data.foliage.type.GrowthModel;
|
import electrosphere.game.data.foliage.type.GrowthModel;
|
||||||
import electrosphere.game.data.foliage.type.TreeModel;
|
import electrosphere.game.data.foliage.type.TreeModel;
|
||||||
import electrosphere.game.data.graphics.GraphicsTemplate;
|
import electrosphere.game.data.graphics.GraphicsTemplate;
|
||||||
|
import electrosphere.game.data.particle.ParticleEmitter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common data that all entity types use
|
* Common data that all entity types use
|
||||||
@ -137,6 +138,11 @@ public class CommonEntityType {
|
|||||||
*/
|
*/
|
||||||
PointLightDescription pointLight;
|
PointLightDescription pointLight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The particle emitter assigned to the entity
|
||||||
|
*/
|
||||||
|
ParticleEmitter particleEmitter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the id for this creature type
|
* Gets the id for this creature type
|
||||||
* @return The id
|
* @return The id
|
||||||
@ -321,4 +327,12 @@ public class CommonEntityType {
|
|||||||
return pointLight;
|
return pointLight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the particle emitter data
|
||||||
|
* @return The particle emitter data
|
||||||
|
*/
|
||||||
|
public ParticleEmitter getParticleEmitter(){
|
||||||
|
return particleEmitter;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package electrosphere.game.data.particle;
|
package electrosphere.game.data.particle;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data on how a particle should behave
|
* Data on how a particle should behave
|
||||||
*/
|
*/
|
||||||
@ -16,7 +18,6 @@ public class ParticleData {
|
|||||||
*/
|
*/
|
||||||
Integer maxLife;
|
Integer maxLife;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The life the particle starts with
|
* The life the particle starts with
|
||||||
*/
|
*/
|
||||||
@ -26,7 +27,7 @@ public class ParticleData {
|
|||||||
/**
|
/**
|
||||||
* The initial velocity of the particle
|
* The initial velocity of the particle
|
||||||
*/
|
*/
|
||||||
Float velocity;
|
Vector3d velocity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The acceleration of the particle
|
* The acceleration of the particle
|
||||||
@ -43,6 +44,11 @@ public class ParticleData {
|
|||||||
*/
|
*/
|
||||||
Float size;
|
Float size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color of the particle
|
||||||
|
*/
|
||||||
|
Vector3d color;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the max life of the particle
|
* Gets the max life of the particle
|
||||||
* @return The max life
|
* @return The max life
|
||||||
@ -63,7 +69,7 @@ public class ParticleData {
|
|||||||
* Gets the starting velocity of the particle
|
* Gets the starting velocity of the particle
|
||||||
* @return The starting velocity
|
* @return The starting velocity
|
||||||
*/
|
*/
|
||||||
public Float getVelocity(){
|
public Vector3d getVelocity(){
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,4 +105,38 @@ public class ParticleData {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxLife(Integer maxLife) {
|
||||||
|
this.maxLife = maxLife;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLifeCurrent(Integer lifeCurrent) {
|
||||||
|
this.lifeCurrent = lifeCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVelocity(Vector3d velocity) {
|
||||||
|
this.velocity = velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAcceleration(Float acceleration) {
|
||||||
|
this.acceleration = acceleration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTexture(String texture) {
|
||||||
|
this.texture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSize(Float size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(Vector3d color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,166 @@
|
|||||||
|
package electrosphere.game.data.particle;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a particle emitter
|
||||||
|
*/
|
||||||
|
public class ParticleEmitter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the particle type
|
||||||
|
*/
|
||||||
|
String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum life of the particle
|
||||||
|
*/
|
||||||
|
Integer maxLife;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The life the particle starts with
|
||||||
|
*/
|
||||||
|
Integer lifeCurrent;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initial velocity of the particle
|
||||||
|
*/
|
||||||
|
Vector3d particleVelocity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The acceleration of the particle
|
||||||
|
*/
|
||||||
|
Float acceleration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The texture of the particle
|
||||||
|
*/
|
||||||
|
String texture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the particle
|
||||||
|
*/
|
||||||
|
Float size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color of the particle
|
||||||
|
*/
|
||||||
|
Vector3d color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of particles to emit per frame
|
||||||
|
*/
|
||||||
|
Float frequency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the max life of the particle
|
||||||
|
* @return The max life
|
||||||
|
*/
|
||||||
|
public Integer getMaxLife(){
|
||||||
|
return maxLife;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the starting life of the particle
|
||||||
|
* @return The starting life
|
||||||
|
*/
|
||||||
|
public Integer getLifeCurrent(){
|
||||||
|
return lifeCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the starting velocity of the particle
|
||||||
|
* @return The starting velocity
|
||||||
|
*/
|
||||||
|
public Vector3d getParticleVelocity(){
|
||||||
|
return particleVelocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the acceleration of the particle
|
||||||
|
* @return The acceleration
|
||||||
|
*/
|
||||||
|
public Float getAcceleration(){
|
||||||
|
return acceleration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the texture of the particle
|
||||||
|
* @return The texture
|
||||||
|
*/
|
||||||
|
public String getTexture(){
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the particle type
|
||||||
|
* @return The name of the particle type
|
||||||
|
*/
|
||||||
|
public String getName(){
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the size of the particle
|
||||||
|
* @return The size of the particle
|
||||||
|
*/
|
||||||
|
public Float getSize(){
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of particles to emit per frame
|
||||||
|
* @return The number of particles to emit per frame
|
||||||
|
*/
|
||||||
|
public Float getFrequency(){
|
||||||
|
return frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the color of the particles generated by the emitted
|
||||||
|
* @return The color
|
||||||
|
*/
|
||||||
|
public Vector3d getColor(){
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxLife(Integer maxLife) {
|
||||||
|
this.maxLife = maxLife;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLifeCurrent(Integer lifeCurrent) {
|
||||||
|
this.lifeCurrent = lifeCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParticleVelocity(Vector3d particleVelocity) {
|
||||||
|
this.particleVelocity = particleVelocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAcceleration(Float acceleration) {
|
||||||
|
this.acceleration = acceleration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTexture(String texture) {
|
||||||
|
this.texture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSize(Float size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(Vector3d color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrequency(Float frequency){
|
||||||
|
this.frequency = frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,12 +5,11 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.renderer.OpenGLState;
|
import electrosphere.renderer.OpenGLState;
|
||||||
import electrosphere.renderer.RenderPipelineState;
|
import electrosphere.renderer.RenderPipelineState;
|
||||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
|
||||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||||
|
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||||
import electrosphere.renderer.model.Model;
|
import electrosphere.renderer.model.Model;
|
||||||
import electrosphere.renderer.shader.ShaderProgram;
|
import electrosphere.renderer.shader.ShaderProgram;
|
||||||
|
|
||||||
@ -67,6 +66,33 @@ public class InstanceManager {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instanced actor of a model at a given model path
|
||||||
|
* @param modelPath The path for the model
|
||||||
|
* @return The instanced actor
|
||||||
|
*/
|
||||||
|
public InstancedActor createInstancedActor(
|
||||||
|
String modelPath,
|
||||||
|
String vertexShaderPath,
|
||||||
|
String fragmentShaderPath,
|
||||||
|
StridedInstanceData instanceData,
|
||||||
|
int capacity
|
||||||
|
){
|
||||||
|
InstancedActor rVal = new InstancedActor(modelPath);
|
||||||
|
if(!pathToInstanceData.containsKey(modelPath)){
|
||||||
|
//queue shader
|
||||||
|
Globals.assetManager.addShaderToQueue(vertexShaderPath, fragmentShaderPath);
|
||||||
|
//if asset manager doesn't have model, queue model
|
||||||
|
if(Globals.assetManager.fetchModel(modelPath) == null){
|
||||||
|
Globals.assetManager.addModelPathToQueue(modelPath);
|
||||||
|
}
|
||||||
|
//register to internal-to-manager datastructures
|
||||||
|
pathToInstanceData.put(modelPath,instanceData);
|
||||||
|
modelsToDraw.add(modelPath);
|
||||||
|
}
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws all models that are queued in this instance manager
|
* Draws all models that are queued in this instance manager
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -6,9 +6,13 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.joml.Matrix4d;
|
import org.joml.Matrix4d;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Quaterniond;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
import org.joml.Sphered;
|
import org.joml.Sphered;
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
import org.joml.Vector4d;
|
||||||
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
@ -116,8 +120,18 @@ public class InstancedActor implements Comparable<InstancedActor> {
|
|||||||
attributes.put(attribute, value);
|
attributes.put(attribute, value);
|
||||||
} else if(value instanceof Vector3f){
|
} else if(value instanceof Vector3f){
|
||||||
attributes.put(attribute, value);
|
attributes.put(attribute, value);
|
||||||
|
} else if(value instanceof Vector3d){
|
||||||
|
attributes.put(attribute, value);
|
||||||
|
} else if(value instanceof Vector4d){
|
||||||
|
attributes.put(attribute, value);
|
||||||
|
} else if(value instanceof Vector4f){
|
||||||
|
attributes.put(attribute, value);
|
||||||
|
} else if(value instanceof Quaterniond){
|
||||||
|
attributes.put(attribute, value);
|
||||||
|
} else if(value instanceof Quaternionf){
|
||||||
|
attributes.put(attribute, value);
|
||||||
} else {
|
} else {
|
||||||
LoggerInterface.loggerRenderer.ERROR("Unsupported operation", new Exception());
|
LoggerInterface.loggerRenderer.ERROR("Unsupported operation " + value, new Exception());
|
||||||
}
|
}
|
||||||
// attributes.put(attribute, value);
|
// attributes.put(attribute, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,10 +13,10 @@ import org.joml.Vector3f;
|
|||||||
import org.joml.Vector4d;
|
import org.joml.Vector4d;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
|
||||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer;
|
import electrosphere.renderer.buffer.HomogenousUniformBuffer;
|
||||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||||
import electrosphere.renderer.buffer.ShaderStorageBuffer;
|
import electrosphere.renderer.buffer.ShaderStorageBuffer;
|
||||||
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.renderer.OpenGLState;
|
import electrosphere.renderer.OpenGLState;
|
||||||
import electrosphere.renderer.RenderPipelineState;
|
import electrosphere.renderer.RenderPipelineState;
|
||||||
import electrosphere.renderer.buffer.BufferEnums.BufferAccess;
|
import electrosphere.renderer.buffer.BufferEnums.BufferAccess;
|
||||||
@ -27,7 +27,7 @@ import electrosphere.renderer.buffer.BufferEnums.BufferUsage;
|
|||||||
*/
|
*/
|
||||||
public class StridedInstanceData implements InstanceData {
|
public class StridedInstanceData implements InstanceData {
|
||||||
|
|
||||||
//the capacity (number of instanced) of this data block. Defaults to 100
|
//the capacity (number of instances) of this data block. Defaults to 1000
|
||||||
int capacity = 1000;
|
int capacity = 1000;
|
||||||
|
|
||||||
//shader paths
|
//shader paths
|
||||||
@ -45,35 +45,60 @@ public class StridedInstanceData implements InstanceData {
|
|||||||
Map<Integer,InstancedActor> indexActorMap = new HashMap<Integer,InstancedActor>();
|
Map<Integer,InstancedActor> indexActorMap = new HashMap<Integer,InstancedActor>();
|
||||||
|
|
||||||
//list of all attribute indices in use by this instance data
|
//list of all attribute indices in use by this instance data
|
||||||
List<ShaderAttribute> attributeIndices = new LinkedList<ShaderAttribute>();
|
List<ShaderAttribute> attributes;
|
||||||
|
|
||||||
//the SSBO
|
//the SSBO
|
||||||
ShaderStorageBuffer buffer;
|
ShaderStorageBuffer buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index to bind to
|
||||||
|
*/
|
||||||
|
int bindPoint;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param capacity Capacity of the buffer (number of elements) backing this data
|
* @param capacity Capacity of the buffer (number of elements) backing this data
|
||||||
*/
|
*/
|
||||||
public StridedInstanceData(int capacity, List<HomogenousBufferTypes> types, String vertexPath, String fragmentPath){
|
public StridedInstanceData(int capacity, int bindPoint, List<ShaderAttribute> attributes, String vertexPath, String fragmentPath){
|
||||||
int entrySize = 0;
|
int entrySize = 0;
|
||||||
for(HomogenousBufferTypes type : types){
|
boolean hitMat = false;
|
||||||
entrySize = entrySize + HomogenousUniformBuffer.calculateTypeSize(type);
|
boolean hitVec = false;
|
||||||
|
boolean hitPrimitive = false;
|
||||||
|
for(ShaderAttribute attribute : attributes){
|
||||||
|
entrySize = entrySize + HomogenousUniformBuffer.calculateTypeSize(attribute.getType());
|
||||||
|
switch(attribute.getType()){
|
||||||
|
case MAT4D:
|
||||||
|
case MAT4F: {
|
||||||
|
hitMat = true;
|
||||||
|
} break;
|
||||||
|
case VEC3D:
|
||||||
|
case VEC3F:
|
||||||
|
case VEC4D:
|
||||||
|
case VEC4F: {
|
||||||
|
hitVec = true;
|
||||||
|
} break;
|
||||||
|
case INT:
|
||||||
|
case DOUBLE:
|
||||||
|
case FLOAT: {
|
||||||
|
hitPrimitive = true;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if(hitPrimitive && (hitMat || hitVec)){
|
||||||
|
String message = "Warning! You are mixing a larger alignment type (vec, mat) with primitives (int, float)!\n" +
|
||||||
|
"This can potentially cause alignment bugs. See hhttps://learnopengl.com/Advanced-OpenGL/Advanced-GLSL or \n" +
|
||||||
|
"https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)#Memory_layout for details on memory layout!"
|
||||||
|
;
|
||||||
|
LoggerInterface.loggerRenderer.WARNING(message);
|
||||||
|
}
|
||||||
|
this.attributes = attributes;
|
||||||
this.capacity = capacity;
|
this.capacity = capacity;
|
||||||
this.vertexShaderPath = vertexPath;
|
this.vertexShaderPath = vertexPath;
|
||||||
this.fragmentShaderPath = fragmentPath;
|
this.fragmentShaderPath = fragmentPath;
|
||||||
actorQueue = new LinkedList<InstancedActor>();
|
actorQueue = new LinkedList<InstancedActor>();
|
||||||
this.buffer = new ShaderStorageBuffer(capacity * entrySize, BufferUsage.STREAM, BufferAccess.DRAW);
|
this.buffer = new ShaderStorageBuffer(capacity * entrySize, BufferUsage.STREAM, BufferAccess.DRAW);
|
||||||
}
|
this.bindPoint = bindPoint;
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new type of attribute to this instance data block
|
|
||||||
* @param shaderAttribute The shader attribute
|
|
||||||
* @param type The type of the attribute
|
|
||||||
*/
|
|
||||||
protected void addDataType(ShaderAttribute shaderAttribute, HomogenousBufferTypes type){
|
|
||||||
attributeIndices.add(shaderAttribute);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -108,90 +133,96 @@ public class StridedInstanceData implements InstanceData {
|
|||||||
public void fillBuffers(){
|
public void fillBuffers(){
|
||||||
int i = 0;
|
int i = 0;
|
||||||
ByteBuffer byteBuff = this.buffer.getBuffer();
|
ByteBuffer byteBuff = this.buffer.getBuffer();
|
||||||
|
byteBuff.limit(byteBuff.capacity());
|
||||||
//buffer data
|
//buffer data
|
||||||
for(InstancedActor actor : actorQueue){
|
for(InstancedActor actor : actorQueue){
|
||||||
//push values to attribute buffers
|
//push values to attribute buffers
|
||||||
for(ShaderAttribute attribute : attributeIndices){
|
for(ShaderAttribute attribute : attributes){
|
||||||
switch(attribute.getType()){
|
if(actor.getAttributeValue(attribute) != null){
|
||||||
case VEC3F: {
|
switch(attribute.getType()){
|
||||||
Vector3f vec = (Vector3f)actor.getAttributeValue(attribute);
|
case VEC3F: {
|
||||||
byteBuff.putFloat(vec.x);
|
Vector3f vec = (Vector3f)actor.getAttributeValue(attribute);
|
||||||
byteBuff.putFloat(vec.y);
|
byteBuff.putFloat(vec.x);
|
||||||
byteBuff.putFloat(vec.z);
|
byteBuff.putFloat(vec.y);
|
||||||
} break;
|
byteBuff.putFloat(vec.z);
|
||||||
case VEC3D: {
|
} break;
|
||||||
Vector3d vec = (Vector3d)actor.getAttributeValue(attribute);
|
case VEC3D: {
|
||||||
byteBuff.putDouble(vec.x);
|
Vector3d vec = (Vector3d)actor.getAttributeValue(attribute);
|
||||||
byteBuff.putDouble(vec.y);
|
byteBuff.putDouble(vec.x);
|
||||||
byteBuff.putDouble(vec.z);
|
byteBuff.putDouble(vec.y);
|
||||||
} break;
|
byteBuff.putDouble(vec.z);
|
||||||
case VEC4F: {
|
} break;
|
||||||
Vector4f vec = (Vector4f)actor.getAttributeValue(attribute);
|
case VEC4F: {
|
||||||
byteBuff.putFloat(vec.w);
|
Vector4f vec = (Vector4f)actor.getAttributeValue(attribute);
|
||||||
byteBuff.putFloat(vec.x);
|
byteBuff.putFloat(vec.w);
|
||||||
byteBuff.putFloat(vec.y);
|
byteBuff.putFloat(vec.x);
|
||||||
byteBuff.putFloat(vec.z);
|
byteBuff.putFloat(vec.y);
|
||||||
} break;
|
byteBuff.putFloat(vec.z);
|
||||||
case VEC4D: {
|
} break;
|
||||||
Vector4d vec = (Vector4d)actor.getAttributeValue(attribute);
|
case VEC4D: {
|
||||||
byteBuff.putDouble(vec.w);
|
Vector4d vec = (Vector4d)actor.getAttributeValue(attribute);
|
||||||
byteBuff.putDouble(vec.x);
|
byteBuff.putDouble(vec.w);
|
||||||
byteBuff.putDouble(vec.y);
|
byteBuff.putDouble(vec.x);
|
||||||
byteBuff.putDouble(vec.z);
|
byteBuff.putDouble(vec.y);
|
||||||
} break;
|
byteBuff.putDouble(vec.z);
|
||||||
case MAT4F: {
|
} break;
|
||||||
Matrix4f mat = (Matrix4f)actor.getAttributeValue(attribute);
|
case MAT4F: {
|
||||||
byteBuff.putFloat(mat.m00());
|
Matrix4f mat = (Matrix4f)actor.getAttributeValue(attribute);
|
||||||
byteBuff.putFloat(mat.m01());
|
byteBuff.putFloat(mat.m00());
|
||||||
byteBuff.putFloat(mat.m02());
|
byteBuff.putFloat(mat.m01());
|
||||||
byteBuff.putFloat(mat.m03());
|
byteBuff.putFloat(mat.m02());
|
||||||
|
byteBuff.putFloat(mat.m03());
|
||||||
|
|
||||||
byteBuff.putFloat(mat.m10());
|
byteBuff.putFloat(mat.m10());
|
||||||
byteBuff.putFloat(mat.m11());
|
byteBuff.putFloat(mat.m11());
|
||||||
byteBuff.putFloat(mat.m12());
|
byteBuff.putFloat(mat.m12());
|
||||||
byteBuff.putFloat(mat.m13());
|
byteBuff.putFloat(mat.m13());
|
||||||
|
|
||||||
byteBuff.putFloat(mat.m20());
|
byteBuff.putFloat(mat.m20());
|
||||||
byteBuff.putFloat(mat.m21());
|
byteBuff.putFloat(mat.m21());
|
||||||
byteBuff.putFloat(mat.m22());
|
byteBuff.putFloat(mat.m22());
|
||||||
byteBuff.putFloat(mat.m23());
|
byteBuff.putFloat(mat.m23());
|
||||||
|
|
||||||
byteBuff.putFloat(mat.m30());
|
byteBuff.putFloat(mat.m30());
|
||||||
byteBuff.putFloat(mat.m31());
|
byteBuff.putFloat(mat.m31());
|
||||||
byteBuff.putFloat(mat.m32());
|
byteBuff.putFloat(mat.m32());
|
||||||
byteBuff.putFloat(mat.m33());
|
byteBuff.putFloat(mat.m33());
|
||||||
} break;
|
} break;
|
||||||
case MAT4D: {
|
case MAT4D: {
|
||||||
Matrix4d mat = (Matrix4d)actor.getAttributeValue(attribute);
|
Matrix4d mat = (Matrix4d)actor.getAttributeValue(attribute);
|
||||||
byteBuff.putDouble((float)mat.m00());
|
byteBuff.putDouble((float)mat.m00());
|
||||||
byteBuff.putDouble((float)mat.m01());
|
byteBuff.putDouble((float)mat.m01());
|
||||||
byteBuff.putDouble((float)mat.m02());
|
byteBuff.putDouble((float)mat.m02());
|
||||||
byteBuff.putDouble((float)mat.m03());
|
byteBuff.putDouble((float)mat.m03());
|
||||||
|
|
||||||
byteBuff.putDouble((float)mat.m10());
|
byteBuff.putDouble((float)mat.m10());
|
||||||
byteBuff.putDouble((float)mat.m11());
|
byteBuff.putDouble((float)mat.m11());
|
||||||
byteBuff.putDouble((float)mat.m12());
|
byteBuff.putDouble((float)mat.m12());
|
||||||
byteBuff.putDouble((float)mat.m13());
|
byteBuff.putDouble((float)mat.m13());
|
||||||
|
|
||||||
byteBuff.putDouble((float)mat.m20());
|
byteBuff.putDouble((float)mat.m20());
|
||||||
byteBuff.putDouble((float)mat.m21());
|
byteBuff.putDouble((float)mat.m21());
|
||||||
byteBuff.putDouble((float)mat.m22());
|
byteBuff.putDouble((float)mat.m22());
|
||||||
byteBuff.putDouble((float)mat.m23());
|
byteBuff.putDouble((float)mat.m23());
|
||||||
|
|
||||||
byteBuff.putDouble((float)mat.m30());
|
byteBuff.putDouble((float)mat.m30());
|
||||||
byteBuff.putDouble((float)mat.m31());
|
byteBuff.putDouble((float)mat.m31());
|
||||||
byteBuff.putDouble((float)mat.m32());
|
byteBuff.putDouble((float)mat.m32());
|
||||||
byteBuff.putDouble((float)mat.m33());
|
byteBuff.putDouble((float)mat.m33());
|
||||||
} break;
|
} break;
|
||||||
case DOUBLE: {
|
case DOUBLE: {
|
||||||
byteBuff.putDouble((Double)actor.getAttributeValue(attribute));
|
byteBuff.putDouble((Double)actor.getAttributeValue(attribute));
|
||||||
} break;
|
} break;
|
||||||
case FLOAT: {
|
case FLOAT: {
|
||||||
byteBuff.putFloat((Float)actor.getAttributeValue(attribute));
|
byteBuff.putFloat((Float)actor.getAttributeValue(attribute));
|
||||||
} break;
|
} break;
|
||||||
case INT: {
|
case INT: {
|
||||||
byteBuff.putInt((Integer)actor.getAttributeValue(attribute));
|
byteBuff.putInt((Integer)actor.getAttributeValue(attribute));
|
||||||
} break;
|
} break;
|
||||||
|
default: {
|
||||||
|
throw new Error("Unhandled attribute type!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//increment
|
//increment
|
||||||
@ -224,7 +255,8 @@ public class StridedInstanceData implements InstanceData {
|
|||||||
@Override
|
@Override
|
||||||
public void upload(OpenGLState openGLState, RenderPipelineState renderPipelineState){
|
public void upload(OpenGLState openGLState, RenderPipelineState renderPipelineState){
|
||||||
this.buffer.upload(openGLState);
|
this.buffer.upload(openGLState);
|
||||||
openGLState.glBindBufferBase(0, buffer);
|
openGLState.glBindBufferBase(this.bindPoint, buffer);
|
||||||
|
renderPipelineState.setInstanceCount(this.getDrawCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -15,6 +15,11 @@ public class ShaderAttribute {
|
|||||||
//for multi-attribute index types (mat4f, mat4d, etc)
|
//for multi-attribute index types (mat4f, mat4d, etc)
|
||||||
int[] attributeIndices;
|
int[] attributeIndices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the attribute
|
||||||
|
*/
|
||||||
|
String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the attribute
|
* The type of the attribute
|
||||||
*/
|
*/
|
||||||
@ -39,10 +44,11 @@ public class ShaderAttribute {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for 1-1 attribute
|
* Constructor for 1-1 attribute
|
||||||
* @param attributeIndex The attribute index
|
* @param name The name of the attribute
|
||||||
|
* @param type The type of attribute
|
||||||
*/
|
*/
|
||||||
public ShaderAttribute(int attributeIndex, HomogenousBufferTypes type){
|
public ShaderAttribute(String name, HomogenousBufferTypes type){
|
||||||
this.attributeIndex = attributeIndex;
|
this.name = name;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,4 +84,12 @@ public class ShaderAttribute {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the attribute
|
||||||
|
* @return The name
|
||||||
|
*/
|
||||||
|
public String getName(){
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user