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": [
|
||||
"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",
|
||||
"maxLife" : 7,
|
||||
"lifeCurrent" : 0,
|
||||
"velocity" : 0.3,
|
||||
"velocity" : {
|
||||
"x": 0.3,
|
||||
"y": 0.3,
|
||||
"z": 0.3
|
||||
},
|
||||
"acceleration" : -0.1,
|
||||
"size": 0.15,
|
||||
"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
|
||||
#Thu Sep 19 15:35:07 EDT 2024
|
||||
buildNumber=339
|
||||
#Thu Sep 19 21:21:28 EDT 2024
|
||||
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)
|
||||
- Also because the client doesn't scan border chunks to see if they should update
|
||||
Fix shader program bug with no-bone variants
|
||||
Particle Emitter work (it renders! it has management!)
|
||||
|
||||
|
||||
# TODO
|
||||
|
||||
@ -2,6 +2,7 @@ package electrosphere.client.entity.instance;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import electrosphere.renderer.actor.instance.StridedInstanceData;
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||
|
||||
@ -19,6 +20,16 @@ public class InstanceTemplate {
|
||||
//The map of all attributes for instanced foliage
|
||||
protected Map<ShaderAttribute,HomogenousBufferTypes> attributes;
|
||||
|
||||
/**
|
||||
* The strided instance data
|
||||
*/
|
||||
protected StridedInstanceData stridedInstanceData;
|
||||
|
||||
/**
|
||||
* The bind point for the data
|
||||
*/
|
||||
int dataBindPoint;
|
||||
|
||||
//shader paths
|
||||
protected String vertexPath;
|
||||
protected String fragmentPath;
|
||||
@ -42,6 +53,26 @@ public class InstanceTemplate {
|
||||
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
|
||||
*/
|
||||
public static InstancedActor makeEntityInstanced(Entity entity, InstanceTemplate template){
|
||||
InstancedActor instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
||||
template.modelPath,
|
||||
template.vertexPath,
|
||||
template.fragmentPath,
|
||||
template.attributes,
|
||||
template.capacity);
|
||||
InstancedActor instancedActor = null;
|
||||
if(template.attributes != null){
|
||||
instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
||||
template.modelPath,
|
||||
template.vertexPath,
|
||||
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.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
||||
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
|
||||
*/
|
||||
public static InstancedActor makeEntityInstancedWithModelTransform(Entity entity, InstanceTemplate template, ShaderAttribute modelTransformAttribute){
|
||||
InstancedActor instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
||||
template.modelPath,
|
||||
template.vertexPath,
|
||||
template.fragmentPath,
|
||||
template.attributes,
|
||||
template.capacity);
|
||||
InstancedActor instancedActor = null;
|
||||
if(template.attributes != null){
|
||||
instancedActor = Globals.clientInstanceManager.createInstancedActor(
|
||||
template.modelPath,
|
||||
template.vertexPath,
|
||||
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.DATA_STRING_POSITION, new Vector3d(0,0,0));
|
||||
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.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.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.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
|
||||
/**
|
||||
* The particle service
|
||||
@ -18,16 +29,20 @@ public class ParticleService extends SignalServiceImpl {
|
||||
*/
|
||||
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
|
||||
*/
|
||||
static final String VERTEX_SHADER_PATH = "";
|
||||
static final String VERTEX_SHADER_PATH = "Shaders/entities/particle/particle.vs";
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The template to use when creating instanced actors
|
||||
*/
|
||||
InstanceTemplate instanceTemplate;
|
||||
|
||||
|
||||
ShaderAttribute modelAttrib;
|
||||
|
||||
ShaderAttribute colorAttrib;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@ -55,17 +80,14 @@ public class ParticleService extends SignalServiceImpl {
|
||||
boolean rVal = false;
|
||||
switch(signal.getType()){
|
||||
case RENDERING_ENGINE_READY: {
|
||||
List<HomogenousBufferTypes> types = Arrays.asList(new HomogenousBufferTypes[]{
|
||||
//position
|
||||
HomogenousBufferTypes.VEC3D,
|
||||
//rotation
|
||||
HomogenousBufferTypes.VEC4D,
|
||||
//scale
|
||||
HomogenousBufferTypes.VEC3D,
|
||||
//texture index
|
||||
HomogenousBufferTypes.INT,
|
||||
modelAttrib = new ShaderAttribute("model", HomogenousBufferTypes.MAT4F);
|
||||
colorAttrib = new ShaderAttribute("color", HomogenousBufferTypes.VEC4F);
|
||||
List<ShaderAttribute> types = Arrays.asList(new ShaderAttribute[]{
|
||||
modelAttrib,
|
||||
colorAttrib,
|
||||
});
|
||||
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;
|
||||
} break;
|
||||
default: {
|
||||
@ -73,5 +95,35 @@ public class ParticleService extends SignalServiceImpl {
|
||||
}
|
||||
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;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.assetmanager.AssetDataStrings;
|
||||
import electrosphere.entity.DrawableUtils;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityCreationUtils;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityTags;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.ParticleTree;
|
||||
import electrosphere.entity.state.particle.ClientParticleTree;
|
||||
import electrosphere.entity.state.client.particle.ClientParticleTree;
|
||||
import electrosphere.game.data.particle.ParticleData;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.renderer.actor.ActorTextureMask;
|
||||
@ -16,7 +16,6 @@ import electrosphere.renderer.actor.ActorTextureMask;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/**
|
||||
* Particle utility functions
|
||||
@ -27,15 +26,15 @@ public class ParticleUtils {
|
||||
|
||||
|
||||
|
||||
public static Entity clientSpawnStaticBillboardParticle(){
|
||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||
EntityCreationUtils.makeEntityDrawable(rVal, Globals.particleBillboardModel);
|
||||
ParticleTree particleTree = new ParticleTree(rVal, 10, new Vector3f(0,0,0), 0, 0, false);
|
||||
rVal.putData(EntityDataStrings.TREE_CLIENTPARTICLETREE, particleTree);
|
||||
rVal.putData(EntityDataStrings.IS_PARTICLE, true);
|
||||
Globals.clientSceneWrapper.getScene().registerEntityToTag(rVal, EntityTags.PARTICLE);
|
||||
return rVal;
|
||||
}
|
||||
// public static Entity clientSpawnStaticBillboardParticle(){
|
||||
// Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||
// EntityCreationUtils.makeEntityDrawable(rVal, Globals.particleBillboardModel);
|
||||
// ClientParticleTree particleTree = new ClientParticleTree(rVal, 10, new Vector3f(0,0,0), 0, 0, false);
|
||||
// rVal.putData(EntityDataStrings.TREE_CLIENTPARTICLETREE, particleTree);
|
||||
// rVal.putData(EntityDataStrings.IS_PARTICLE, true);
|
||||
// Globals.clientSceneWrapper.getScene().registerEntityToTag(rVal, EntityTags.PARTICLE);
|
||||
// return rVal;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Spawns a billboard particle
|
||||
@ -45,7 +44,7 @@ public class ParticleUtils {
|
||||
*/
|
||||
public static Entity clientSpawnBillboardParticle(ParticleData data, Vector3d destination){
|
||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||
EntityCreationUtils.makeEntityDrawable(rVal, Globals.particleBillboardModel);
|
||||
EntityCreationUtils.makeEntityDrawable(rVal, AssetDataStrings.MODEL_PARTICLE);
|
||||
|
||||
//actor logic
|
||||
Actor particleActor = EntityUtils.getActor(rVal);
|
||||
|
||||
@ -76,6 +76,7 @@ public class ClientSimulation {
|
||||
//
|
||||
//update attached entity positions
|
||||
AttachUtils.clientUpdateAttachedEntityPositions();
|
||||
Globals.particleService.handleAllSignals();
|
||||
//
|
||||
//Hitbox stuff
|
||||
Globals.profiler.beginCpuSample("update hitboxes");
|
||||
|
||||
@ -292,7 +292,6 @@ public class Globals {
|
||||
//
|
||||
// Particle stuff
|
||||
//
|
||||
public static String particleBillboardModel;
|
||||
public static ParticleDefinition particleDefinition;
|
||||
public static ParticleService particleService;
|
||||
|
||||
@ -619,7 +618,7 @@ public class Globals {
|
||||
fontManager.loadFonts();
|
||||
assetManager.registerModelToSpecificString(RenderUtils.createBitmapCharacter(), AssetDataStrings.BITMAP_CHARACTER_MODEL);
|
||||
//particle billboard model
|
||||
particleBillboardModel = assetManager.registerModel(RenderUtils.createParticleModel());
|
||||
assetManager.registerModelToSpecificString(RenderUtils.createParticleModel(), AssetDataStrings.MODEL_PARTICLE);
|
||||
//initialize required windows
|
||||
WindowUtils.initBaseWindows();
|
||||
//init default shaderProgram
|
||||
|
||||
@ -15,6 +15,7 @@ public class AssetDataStrings {
|
||||
public static final String UNITSPHERE = "unitSphere";
|
||||
public static final String UNITCYLINDER = "unitCylinder";
|
||||
public static final String UNITCUBE = "unitCube";
|
||||
public static final String MODEL_PARTICLE = "particle";
|
||||
|
||||
/**
|
||||
* UI generic audio
|
||||
|
||||
@ -3,6 +3,7 @@ package electrosphere.entity;
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.types.collision.CollisionObjUtils;
|
||||
|
||||
/**
|
||||
@ -28,7 +29,8 @@ public class ClientEntityUtils {
|
||||
*/
|
||||
public static void destroyEntity(Entity entity){
|
||||
//check for client-specific stuff
|
||||
|
||||
Globals.renderingEngine.getLightManager().destroyPointLight(entity);
|
||||
|
||||
//deregister all behavior trees
|
||||
EntityUtils.cleanUpEntity(entity);
|
||||
}
|
||||
|
||||
@ -260,9 +260,10 @@ public class EntityDataStrings {
|
||||
public static final String TREE_SERVEREQUIPSTATE = "treeServerEquipState";
|
||||
|
||||
/*
|
||||
Light state
|
||||
Client-only components
|
||||
*/
|
||||
public static final String TREE_CLIENTLIGHTSTATE = "treeClientLightState";
|
||||
public static final String TREE_CLIENTPARTICLEEMITTERSTATE = "treeClientParticleEmitterState";
|
||||
|
||||
/*
|
||||
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.Matrix4f;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import electrosphere.client.entity.camera.CameraEntityUtils;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.ClientEntityUtils;
|
||||
import electrosphere.entity.Entity;
|
||||
@ -12,6 +17,7 @@ import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.game.data.particle.ParticleData;
|
||||
import electrosphere.renderer.actor.instance.InstancedActor;
|
||||
|
||||
/**
|
||||
* Particle component for a client-side particle
|
||||
@ -28,15 +34,21 @@ public class ClientParticleTree implements BehaviorTree {
|
||||
//current life
|
||||
int lifeCurrent;
|
||||
|
||||
|
||||
//The destination of the particle
|
||||
Vector3d destination;
|
||||
|
||||
//the velocity of the particle
|
||||
float velocity;
|
||||
Vector3d velocity;
|
||||
|
||||
//the acceleration of the particle
|
||||
float acceleration;
|
||||
|
||||
/**
|
||||
* The data for this particle
|
||||
*/
|
||||
ParticleData particleData;
|
||||
|
||||
/**
|
||||
* The color of the particle
|
||||
*/
|
||||
Vector3d color;
|
||||
|
||||
|
||||
/**
|
||||
@ -48,20 +60,16 @@ public class ClientParticleTree implements BehaviorTree {
|
||||
if(params.length < 1){
|
||||
throw new IllegalArgumentException("No particle data was provided");
|
||||
}
|
||||
if(params.length < 2){
|
||||
throw new IllegalArgumentException("No destination set for the particle");
|
||||
}
|
||||
ParticleData particleData = (ParticleData)params[0];
|
||||
Vector3d destination = (Vector3d)params[1];
|
||||
this.particleData = (ParticleData)params[0];
|
||||
|
||||
//sets data for the tree
|
||||
this.parent = parent;
|
||||
this.maxLife = particleData.getMaxLife();
|
||||
this.destination = destination;
|
||||
this.velocity = particleData.getVelocity();
|
||||
this.acceleration = particleData.getAcceleration();
|
||||
this.hasLife = particleData.getMaxLife() != null;
|
||||
this.lifeCurrent = maxLife;
|
||||
this.color = new Vector3d(new Random().nextFloat(),new Random().nextFloat(),new Random().nextFloat());
|
||||
}
|
||||
|
||||
public int getMaxLife() {
|
||||
@ -72,11 +80,7 @@ public class ClientParticleTree implements BehaviorTree {
|
||||
return lifeCurrent;
|
||||
}
|
||||
|
||||
public Vector3d getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public float getVelocity() {
|
||||
public Vector3d getVelocity() {
|
||||
return velocity;
|
||||
}
|
||||
|
||||
@ -86,17 +90,25 @@ public class ClientParticleTree implements BehaviorTree {
|
||||
|
||||
@Override
|
||||
public void simulate(float deltaTime){
|
||||
InstancedActor instancedActor = InstancedActor.getInstancedActor(parent);
|
||||
Vector3d parentPosition = EntityUtils.getPosition(parent);
|
||||
parentPosition.add(new Vector3d(destination).mul(velocity));
|
||||
velocity = velocity + acceleration;
|
||||
if(velocity < 0){
|
||||
velocity = 0;
|
||||
Vector3f cameraPos = CameraEntityUtils.getCameraCenter(Globals.playerCamera);
|
||||
|
||||
//update position
|
||||
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;
|
||||
}
|
||||
if(hasLife){
|
||||
lifeCurrent--;
|
||||
if(lifeCurrent <= 0){
|
||||
ClientEntityUtils.destroyEntity(parent);
|
||||
Globals.clientSceneWrapper.getScene().deregisterBehaviorTree(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,6 +116,19 @@ public class ClientParticleTree implements BehaviorTree {
|
||||
Matrix4f rotationMatrix = new Matrix4f(Globals.viewMatrix).invert();
|
||||
Quaternionf rotation = new Quaternionf(rotationMatrix.getRotation(new AxisAngle4f()));
|
||||
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
|
||||
*/
|
||||
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.block.ClientBlockTree;
|
||||
import electrosphere.entity.state.block.ServerBlockTree;
|
||||
import electrosphere.entity.state.client.particle.ClientParticleEmitterComponent;
|
||||
import electrosphere.entity.state.equip.ClientEquipState;
|
||||
import electrosphere.entity.state.equip.ServerEquipState;
|
||||
import electrosphere.entity.state.gravity.ClientGravityTree;
|
||||
@ -257,6 +258,15 @@ public class CommonEntityUtils {
|
||||
ClientPointLightComponent.attachTree(entity, rawType.getPointLight());
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Particle emitter
|
||||
//
|
||||
//
|
||||
if(rawType.getParticleEmitter() != null){
|
||||
ClientParticleEmitterComponent.attachTree(entity, rawType.getParticleEmitter());
|
||||
}
|
||||
|
||||
if(rawType.getEquipPoints() != null && rawType.getEquipPoints().size() > 0){
|
||||
ClientEquipState.attachTree(entity, 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.TreeModel;
|
||||
import electrosphere.game.data.graphics.GraphicsTemplate;
|
||||
import electrosphere.game.data.particle.ParticleEmitter;
|
||||
|
||||
/**
|
||||
* Common data that all entity types use
|
||||
@ -137,6 +138,11 @@ public class CommonEntityType {
|
||||
*/
|
||||
PointLightDescription pointLight;
|
||||
|
||||
/**
|
||||
* The particle emitter assigned to the entity
|
||||
*/
|
||||
ParticleEmitter particleEmitter;
|
||||
|
||||
/**
|
||||
* Gets the id for this creature type
|
||||
* @return The id
|
||||
@ -321,4 +327,12 @@ public class CommonEntityType {
|
||||
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;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
/**
|
||||
* Data on how a particle should behave
|
||||
*/
|
||||
@ -16,7 +18,6 @@ public class ParticleData {
|
||||
*/
|
||||
Integer maxLife;
|
||||
|
||||
|
||||
/**
|
||||
* The life the particle starts with
|
||||
*/
|
||||
@ -26,7 +27,7 @@ public class ParticleData {
|
||||
/**
|
||||
* The initial velocity of the particle
|
||||
*/
|
||||
Float velocity;
|
||||
Vector3d velocity;
|
||||
|
||||
/**
|
||||
* The acceleration of the particle
|
||||
@ -43,6 +44,11 @@ public class ParticleData {
|
||||
*/
|
||||
Float size;
|
||||
|
||||
/**
|
||||
* The color of the particle
|
||||
*/
|
||||
Vector3d color;
|
||||
|
||||
/**
|
||||
* Gets the max life of the particle
|
||||
* @return The max life
|
||||
@ -63,7 +69,7 @@ public class ParticleData {
|
||||
* Gets the starting velocity of the particle
|
||||
* @return The starting velocity
|
||||
*/
|
||||
public Float getVelocity(){
|
||||
public Vector3d getVelocity(){
|
||||
return velocity;
|
||||
}
|
||||
|
||||
@ -99,4 +105,38 @@ public class ParticleData {
|
||||
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.Map;
|
||||
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.renderer.OpenGLState;
|
||||
import electrosphere.renderer.RenderPipelineState;
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
import electrosphere.renderer.model.Model;
|
||||
import electrosphere.renderer.shader.ShaderProgram;
|
||||
|
||||
@ -67,6 +66,33 @@ public class InstanceManager {
|
||||
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
|
||||
*/
|
||||
|
||||
@ -6,9 +6,13 @@ import java.util.Map;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Sphered;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4d;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
@ -116,8 +120,18 @@ public class InstancedActor implements Comparable<InstancedActor> {
|
||||
attributes.put(attribute, value);
|
||||
} else if(value instanceof Vector3f){
|
||||
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 {
|
||||
LoggerInterface.loggerRenderer.ERROR("Unsupported operation", new Exception());
|
||||
LoggerInterface.loggerRenderer.ERROR("Unsupported operation " + value, new Exception());
|
||||
}
|
||||
// attributes.put(attribute, value);
|
||||
}
|
||||
|
||||
@ -13,10 +13,10 @@ import org.joml.Vector3f;
|
||||
import org.joml.Vector4d;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer.HomogenousBufferTypes;
|
||||
import electrosphere.renderer.buffer.HomogenousUniformBuffer;
|
||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||
import electrosphere.renderer.buffer.ShaderStorageBuffer;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.OpenGLState;
|
||||
import electrosphere.renderer.RenderPipelineState;
|
||||
import electrosphere.renderer.buffer.BufferEnums.BufferAccess;
|
||||
@ -27,7 +27,7 @@ import electrosphere.renderer.buffer.BufferEnums.BufferUsage;
|
||||
*/
|
||||
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;
|
||||
|
||||
//shader paths
|
||||
@ -45,35 +45,60 @@ public class StridedInstanceData implements InstanceData {
|
||||
Map<Integer,InstancedActor> indexActorMap = new HashMap<Integer,InstancedActor>();
|
||||
|
||||
//list of all attribute indices in use by this instance data
|
||||
List<ShaderAttribute> attributeIndices = new LinkedList<ShaderAttribute>();
|
||||
List<ShaderAttribute> attributes;
|
||||
|
||||
//the SSBO
|
||||
ShaderStorageBuffer buffer;
|
||||
|
||||
/**
|
||||
* The index to bind to
|
||||
*/
|
||||
int bindPoint;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @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;
|
||||
for(HomogenousBufferTypes type : types){
|
||||
entrySize = entrySize + HomogenousUniformBuffer.calculateTypeSize(type);
|
||||
boolean hitMat = false;
|
||||
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.vertexShaderPath = vertexPath;
|
||||
this.fragmentShaderPath = fragmentPath;
|
||||
actorQueue = new LinkedList<InstancedActor>();
|
||||
this.buffer = new ShaderStorageBuffer(capacity * entrySize, BufferUsage.STREAM, BufferAccess.DRAW);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
this.bindPoint = bindPoint;
|
||||
}
|
||||
|
||||
|
||||
@ -108,90 +133,96 @@ public class StridedInstanceData implements InstanceData {
|
||||
public void fillBuffers(){
|
||||
int i = 0;
|
||||
ByteBuffer byteBuff = this.buffer.getBuffer();
|
||||
byteBuff.limit(byteBuff.capacity());
|
||||
//buffer data
|
||||
for(InstancedActor actor : actorQueue){
|
||||
//push values to attribute buffers
|
||||
for(ShaderAttribute attribute : attributeIndices){
|
||||
switch(attribute.getType()){
|
||||
case VEC3F: {
|
||||
Vector3f vec = (Vector3f)actor.getAttributeValue(attribute);
|
||||
byteBuff.putFloat(vec.x);
|
||||
byteBuff.putFloat(vec.y);
|
||||
byteBuff.putFloat(vec.z);
|
||||
} break;
|
||||
case VEC3D: {
|
||||
Vector3d vec = (Vector3d)actor.getAttributeValue(attribute);
|
||||
byteBuff.putDouble(vec.x);
|
||||
byteBuff.putDouble(vec.y);
|
||||
byteBuff.putDouble(vec.z);
|
||||
} break;
|
||||
case VEC4F: {
|
||||
Vector4f vec = (Vector4f)actor.getAttributeValue(attribute);
|
||||
byteBuff.putFloat(vec.w);
|
||||
byteBuff.putFloat(vec.x);
|
||||
byteBuff.putFloat(vec.y);
|
||||
byteBuff.putFloat(vec.z);
|
||||
} break;
|
||||
case VEC4D: {
|
||||
Vector4d vec = (Vector4d)actor.getAttributeValue(attribute);
|
||||
byteBuff.putDouble(vec.w);
|
||||
byteBuff.putDouble(vec.x);
|
||||
byteBuff.putDouble(vec.y);
|
||||
byteBuff.putDouble(vec.z);
|
||||
} break;
|
||||
case MAT4F: {
|
||||
Matrix4f mat = (Matrix4f)actor.getAttributeValue(attribute);
|
||||
byteBuff.putFloat(mat.m00());
|
||||
byteBuff.putFloat(mat.m01());
|
||||
byteBuff.putFloat(mat.m02());
|
||||
byteBuff.putFloat(mat.m03());
|
||||
for(ShaderAttribute attribute : attributes){
|
||||
if(actor.getAttributeValue(attribute) != null){
|
||||
switch(attribute.getType()){
|
||||
case VEC3F: {
|
||||
Vector3f vec = (Vector3f)actor.getAttributeValue(attribute);
|
||||
byteBuff.putFloat(vec.x);
|
||||
byteBuff.putFloat(vec.y);
|
||||
byteBuff.putFloat(vec.z);
|
||||
} break;
|
||||
case VEC3D: {
|
||||
Vector3d vec = (Vector3d)actor.getAttributeValue(attribute);
|
||||
byteBuff.putDouble(vec.x);
|
||||
byteBuff.putDouble(vec.y);
|
||||
byteBuff.putDouble(vec.z);
|
||||
} break;
|
||||
case VEC4F: {
|
||||
Vector4f vec = (Vector4f)actor.getAttributeValue(attribute);
|
||||
byteBuff.putFloat(vec.w);
|
||||
byteBuff.putFloat(vec.x);
|
||||
byteBuff.putFloat(vec.y);
|
||||
byteBuff.putFloat(vec.z);
|
||||
} break;
|
||||
case VEC4D: {
|
||||
Vector4d vec = (Vector4d)actor.getAttributeValue(attribute);
|
||||
byteBuff.putDouble(vec.w);
|
||||
byteBuff.putDouble(vec.x);
|
||||
byteBuff.putDouble(vec.y);
|
||||
byteBuff.putDouble(vec.z);
|
||||
} break;
|
||||
case MAT4F: {
|
||||
Matrix4f mat = (Matrix4f)actor.getAttributeValue(attribute);
|
||||
byteBuff.putFloat(mat.m00());
|
||||
byteBuff.putFloat(mat.m01());
|
||||
byteBuff.putFloat(mat.m02());
|
||||
byteBuff.putFloat(mat.m03());
|
||||
|
||||
byteBuff.putFloat(mat.m10());
|
||||
byteBuff.putFloat(mat.m11());
|
||||
byteBuff.putFloat(mat.m12());
|
||||
byteBuff.putFloat(mat.m13());
|
||||
|
||||
byteBuff.putFloat(mat.m20());
|
||||
byteBuff.putFloat(mat.m21());
|
||||
byteBuff.putFloat(mat.m22());
|
||||
byteBuff.putFloat(mat.m23());
|
||||
byteBuff.putFloat(mat.m10());
|
||||
byteBuff.putFloat(mat.m11());
|
||||
byteBuff.putFloat(mat.m12());
|
||||
byteBuff.putFloat(mat.m13());
|
||||
|
||||
byteBuff.putFloat(mat.m20());
|
||||
byteBuff.putFloat(mat.m21());
|
||||
byteBuff.putFloat(mat.m22());
|
||||
byteBuff.putFloat(mat.m23());
|
||||
|
||||
byteBuff.putFloat(mat.m30());
|
||||
byteBuff.putFloat(mat.m31());
|
||||
byteBuff.putFloat(mat.m32());
|
||||
byteBuff.putFloat(mat.m33());
|
||||
} break;
|
||||
case MAT4D: {
|
||||
Matrix4d mat = (Matrix4d)actor.getAttributeValue(attribute);
|
||||
byteBuff.putDouble((float)mat.m00());
|
||||
byteBuff.putDouble((float)mat.m01());
|
||||
byteBuff.putDouble((float)mat.m02());
|
||||
byteBuff.putDouble((float)mat.m03());
|
||||
byteBuff.putFloat(mat.m30());
|
||||
byteBuff.putFloat(mat.m31());
|
||||
byteBuff.putFloat(mat.m32());
|
||||
byteBuff.putFloat(mat.m33());
|
||||
} break;
|
||||
case MAT4D: {
|
||||
Matrix4d mat = (Matrix4d)actor.getAttributeValue(attribute);
|
||||
byteBuff.putDouble((float)mat.m00());
|
||||
byteBuff.putDouble((float)mat.m01());
|
||||
byteBuff.putDouble((float)mat.m02());
|
||||
byteBuff.putDouble((float)mat.m03());
|
||||
|
||||
byteBuff.putDouble((float)mat.m10());
|
||||
byteBuff.putDouble((float)mat.m11());
|
||||
byteBuff.putDouble((float)mat.m12());
|
||||
byteBuff.putDouble((float)mat.m13());
|
||||
|
||||
byteBuff.putDouble((float)mat.m20());
|
||||
byteBuff.putDouble((float)mat.m21());
|
||||
byteBuff.putDouble((float)mat.m22());
|
||||
byteBuff.putDouble((float)mat.m23());
|
||||
byteBuff.putDouble((float)mat.m10());
|
||||
byteBuff.putDouble((float)mat.m11());
|
||||
byteBuff.putDouble((float)mat.m12());
|
||||
byteBuff.putDouble((float)mat.m13());
|
||||
|
||||
byteBuff.putDouble((float)mat.m20());
|
||||
byteBuff.putDouble((float)mat.m21());
|
||||
byteBuff.putDouble((float)mat.m22());
|
||||
byteBuff.putDouble((float)mat.m23());
|
||||
|
||||
byteBuff.putDouble((float)mat.m30());
|
||||
byteBuff.putDouble((float)mat.m31());
|
||||
byteBuff.putDouble((float)mat.m32());
|
||||
byteBuff.putDouble((float)mat.m33());
|
||||
} break;
|
||||
case DOUBLE: {
|
||||
byteBuff.putDouble((Double)actor.getAttributeValue(attribute));
|
||||
} break;
|
||||
case FLOAT: {
|
||||
byteBuff.putFloat((Float)actor.getAttributeValue(attribute));
|
||||
} break;
|
||||
case INT: {
|
||||
byteBuff.putInt((Integer)actor.getAttributeValue(attribute));
|
||||
} break;
|
||||
byteBuff.putDouble((float)mat.m30());
|
||||
byteBuff.putDouble((float)mat.m31());
|
||||
byteBuff.putDouble((float)mat.m32());
|
||||
byteBuff.putDouble((float)mat.m33());
|
||||
} break;
|
||||
case DOUBLE: {
|
||||
byteBuff.putDouble((Double)actor.getAttributeValue(attribute));
|
||||
} break;
|
||||
case FLOAT: {
|
||||
byteBuff.putFloat((Float)actor.getAttributeValue(attribute));
|
||||
} break;
|
||||
case INT: {
|
||||
byteBuff.putInt((Integer)actor.getAttributeValue(attribute));
|
||||
} break;
|
||||
default: {
|
||||
throw new Error("Unhandled attribute type!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//increment
|
||||
@ -224,7 +255,8 @@ public class StridedInstanceData implements InstanceData {
|
||||
@Override
|
||||
public void upload(OpenGLState openGLState, RenderPipelineState renderPipelineState){
|
||||
this.buffer.upload(openGLState);
|
||||
openGLState.glBindBufferBase(0, buffer);
|
||||
openGLState.glBindBufferBase(this.bindPoint, buffer);
|
||||
renderPipelineState.setInstanceCount(this.getDrawCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -15,6 +15,11 @@ public class ShaderAttribute {
|
||||
//for multi-attribute index types (mat4f, mat4d, etc)
|
||||
int[] attributeIndices;
|
||||
|
||||
/**
|
||||
* The name of the attribute
|
||||
*/
|
||||
String name;
|
||||
|
||||
/**
|
||||
* The type of the attribute
|
||||
*/
|
||||
@ -39,10 +44,11 @@ public class ShaderAttribute {
|
||||
|
||||
/**
|
||||
* 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){
|
||||
this.attributeIndex = attributeIndex;
|
||||
public ShaderAttribute(String name, HomogenousBufferTypes type){
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@ -78,4 +84,12 @@ public class ShaderAttribute {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the attribute
|
||||
* @return The name
|
||||
*/
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user