texture atlasing for particle system
Some checks are pending
studiorailgun/Renderer/pipeline/head Build queued...
Some checks are pending
studiorailgun/Renderer/pipeline/head Build queued...
This commit is contained in:
parent
2ef4b13786
commit
4b41ac823c
@ -19,7 +19,7 @@
|
|||||||
"z": 0.0
|
"z": 0.0
|
||||||
},
|
},
|
||||||
"acceleration": -0.01,
|
"acceleration": -0.01,
|
||||||
"texture": "",
|
"texture": "blood1.png",
|
||||||
"size": 0.3,
|
"size": 0.3,
|
||||||
"color": {
|
"color": {
|
||||||
"x": 0.5,
|
"x": 0.5,
|
||||||
|
|||||||
@ -50,7 +50,8 @@ struct Cluster {
|
|||||||
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||||
};
|
};
|
||||||
|
|
||||||
out vec4 FragColor;
|
layout (location = 0) out vec4 accum;
|
||||||
|
layout (location = 1) out float reveal;
|
||||||
|
|
||||||
|
|
||||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||||
@ -119,7 +120,7 @@ void main(){
|
|||||||
|
|
||||||
//get color of base texture
|
//get color of base texture
|
||||||
// vec3 textureColor = vec3((norm.x + 1) / 2.0, norm.y, 1.0 - (norm.x + 1) / 2.0);
|
// vec3 textureColor = vec3((norm.x + 1) / 2.0, norm.y, 1.0 - (norm.x + 1) / 2.0);
|
||||||
vec3 textureColor = color.rgb;
|
vec4 textureColor = texture(material.diffuse,TexCoord);
|
||||||
// vec3 textureColor = vec3(0.17647,0.4,0.09411);//texture(material.diffuse, TexCoord).rgb;
|
// vec3 textureColor = vec3(0.17647,0.4,0.09411);//texture(material.diffuse, TexCoord).rgb;
|
||||||
|
|
||||||
//shadow
|
//shadow
|
||||||
@ -136,19 +137,25 @@ void main(){
|
|||||||
}
|
}
|
||||||
//error checking on light clusters
|
//error checking on light clusters
|
||||||
if(pointLightCount > MAX_LIGHTS_PER_CLUSTER){
|
if(pointLightCount > MAX_LIGHTS_PER_CLUSTER){
|
||||||
FragColor = vec4(1.0f,0.0f,0.0f,1);
|
accum = vec4(1.0f,0.0f,0.0f,1);
|
||||||
|
reveal = textureColor.a;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//calculate final color
|
//calculate final color
|
||||||
vec3 finalColor = textureColor * lightIntensity;// * max(shadow,0.4);
|
vec4 finalColor = textureColor.rgba * vec4(lightIntensity,1.0);// * max(shadow,0.4);
|
||||||
// vec3 lightAmount = CalcDirLight(norm, viewDir);
|
// vec3 lightAmount = CalcDirLight(norm, viewDir);
|
||||||
// for(int i = 0; i < NR_POINT_LIGHTS; i++){
|
// for(int i = 0; i < NR_POINT_LIGHTS; i++){
|
||||||
// lightAmount += CalcPointLight(i, norm, FragPos, viewDir);
|
// lightAmount += CalcPointLight(i, norm, FragPos, viewDir);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
//this final calculation is for transparency
|
//calculate weight function
|
||||||
FragColor = vec4(finalColor, 1.0);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
float weight = clamp(pow(min(1.0, finalColor.a * 10.0) + 0.01, 3.0) * 1e8 *
|
||||||
|
pow(1.0 - gl_FragCoord.z * 0.9, 3.0), 1e-2, 3e3);
|
||||||
|
|
||||||
|
//emit colors
|
||||||
|
accum = vec4(finalColor.rgb * finalColor.a, finalColor.a) * weight;
|
||||||
|
reveal = finalColor.a;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculates the color when using a directional light.
|
// calculates the color when using a directional light.
|
||||||
|
|||||||
@ -12,6 +12,7 @@ A point light
|
|||||||
struct ParticleData {
|
struct ParticleData {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
vec4 color;
|
vec4 color;
|
||||||
|
vec4 texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -64,7 +65,9 @@ void main() {
|
|||||||
FragPos = vec3(model * FinalVertex);
|
FragPos = vec3(model * FinalVertex);
|
||||||
ViewFragPos = vec3(view * model * FinalVertex);
|
ViewFragPos = vec3(view * model * FinalVertex);
|
||||||
Normal = mat3(transpose(inverse(model))) * aNormal;
|
Normal = mat3(transpose(inverse(model))) * aNormal;
|
||||||
TexCoord = aTex;
|
|
||||||
|
//offset based on data stored in particle data
|
||||||
|
TexCoord = (aTex * currentData.texture.xy) + currentData.texture.zw;
|
||||||
|
|
||||||
|
|
||||||
//shadow map stuff
|
//shadow map stuff
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
#maven.buildNumber.plugin properties file
|
#maven.buildNumber.plugin properties file
|
||||||
#Thu Sep 19 21:21:28 EDT 2024
|
#Thu Sep 19 23:04:32 EDT 2024
|
||||||
buildNumber=351
|
buildNumber=355
|
||||||
|
|||||||
@ -1018,6 +1018,8 @@ Upgrade terrain generation algorithms
|
|||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
|
|
||||||
|
Test Creation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import electrosphere.client.entity.instance.InstancedEntityUtils;
|
|||||||
import electrosphere.engine.assetmanager.AssetDataStrings;
|
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.DrawableUtils;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.EntityCreationUtils;
|
import electrosphere.entity.EntityCreationUtils;
|
||||||
import electrosphere.entity.EntityUtils;
|
import electrosphere.entity.EntityUtils;
|
||||||
@ -17,6 +18,7 @@ import electrosphere.entity.state.client.particle.ClientParticleTree;
|
|||||||
import electrosphere.game.data.particle.ParticleData;
|
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.texture.TextureAtlas;
|
||||||
import electrosphere.renderer.buffer.ShaderAttribute;
|
import electrosphere.renderer.buffer.ShaderAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,6 +46,11 @@ public class ParticleService extends SignalServiceImpl {
|
|||||||
*/
|
*/
|
||||||
static final String FRAGMENT_SHADER_PATH = "Shaders/entities/particle/particle.fs";
|
static final String FRAGMENT_SHADER_PATH = "Shaders/entities/particle/particle.fs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The particle texture atlas
|
||||||
|
*/
|
||||||
|
TextureAtlas particleTextureAtlas;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The instance data for the particles
|
* The instance data for the particles
|
||||||
@ -60,6 +67,8 @@ public class ParticleService extends SignalServiceImpl {
|
|||||||
|
|
||||||
ShaderAttribute colorAttrib;
|
ShaderAttribute colorAttrib;
|
||||||
|
|
||||||
|
ShaderAttribute textureAttrib;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
@ -82,9 +91,11 @@ public class ParticleService extends SignalServiceImpl {
|
|||||||
case RENDERING_ENGINE_READY: {
|
case RENDERING_ENGINE_READY: {
|
||||||
modelAttrib = new ShaderAttribute("model", HomogenousBufferTypes.MAT4F);
|
modelAttrib = new ShaderAttribute("model", HomogenousBufferTypes.MAT4F);
|
||||||
colorAttrib = new ShaderAttribute("color", HomogenousBufferTypes.VEC4F);
|
colorAttrib = new ShaderAttribute("color", HomogenousBufferTypes.VEC4F);
|
||||||
|
textureAttrib = new ShaderAttribute("texture", HomogenousBufferTypes.VEC4F);
|
||||||
List<ShaderAttribute> types = Arrays.asList(new ShaderAttribute[]{
|
List<ShaderAttribute> types = Arrays.asList(new ShaderAttribute[]{
|
||||||
modelAttrib,
|
modelAttrib,
|
||||||
colorAttrib,
|
colorAttrib,
|
||||||
|
textureAttrib,
|
||||||
});
|
});
|
||||||
this.particleInstanceData = new StridedInstanceData(MAX_PARTICLES,PARTICLE_SSBO_BIND_POINT,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);
|
this.instanceTemplate = InstanceTemplate.createInstanceTemplate(MAX_PARTICLES, AssetDataStrings.MODEL_PARTICLE, VERTEX_SHADER_PATH, FRAGMENT_SHADER_PATH, particleInstanceData, PARTICLE_SSBO_BIND_POINT);
|
||||||
@ -104,6 +115,22 @@ public class ParticleService extends SignalServiceImpl {
|
|||||||
return this.particleInstanceData;
|
return this.particleInstanceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the particle texture atlas
|
||||||
|
* @param particleTextureAtlas The particle texture atlas
|
||||||
|
*/
|
||||||
|
public void setParticleTextureAtlas(TextureAtlas particleTextureAtlas){
|
||||||
|
this.particleTextureAtlas = particleTextureAtlas;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the texture atlas for the particle texture
|
||||||
|
* @return The atlas
|
||||||
|
*/
|
||||||
|
public TextureAtlas getTextureAtlas(){
|
||||||
|
return particleTextureAtlas;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawns a particle
|
* Spawns a particle
|
||||||
* @param data The particle data for the particle
|
* @param data The particle data for the particle
|
||||||
@ -113,6 +140,7 @@ public class ParticleService extends SignalServiceImpl {
|
|||||||
public Entity spawn(ParticleData data, Vector3d position){
|
public Entity spawn(ParticleData data, Vector3d position){
|
||||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||||
InstancedEntityUtils.makeEntityInstanced(rVal, instanceTemplate);
|
InstancedEntityUtils.makeEntityInstanced(rVal, instanceTemplate);
|
||||||
|
DrawableUtils.makeEntityTransparent(rVal);
|
||||||
EntityUtils.getPosition(rVal).set(position);
|
EntityUtils.getPosition(rVal).set(position);
|
||||||
ClientParticleTree.attachTree(rVal, data);
|
ClientParticleTree.attachTree(rVal, data);
|
||||||
return rVal;
|
return rVal;
|
||||||
@ -125,5 +153,9 @@ public class ParticleService extends SignalServiceImpl {
|
|||||||
public ShaderAttribute getColorAttrib(){
|
public ShaderAttribute getColorAttrib(){
|
||||||
return colorAttrib;
|
return colorAttrib;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ShaderAttribute getTextureAttrib(){
|
||||||
|
return textureAttrib;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,8 @@ 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";
|
public static final String MODEL_PARTICLE = "particleModel";
|
||||||
|
public static final String TEXTURE_PARTICLE = "particleTexture";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI generic audio
|
* UI generic audio
|
||||||
|
|||||||
@ -338,6 +338,15 @@ public class AssetManager {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a texture to a path
|
||||||
|
* @param t The texture
|
||||||
|
* @param path The path
|
||||||
|
*/
|
||||||
|
public void registerTextureToPath(Texture t, String path){
|
||||||
|
texturesLoadedIntoMemory.put(path,t);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasLoadedTexture(String path){
|
public boolean hasLoadedTexture(String path){
|
||||||
return texturesLoadedIntoMemory.containsKey(path);
|
return texturesLoadedIntoMemory.containsKey(path);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,17 +2,21 @@ package electrosphere.engine.loadingthreads;
|
|||||||
|
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
import electrosphere.client.terrain.cells.VoxelTextureAtlas;
|
import electrosphere.client.terrain.cells.VoxelTextureAtlas;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.engine.assetmanager.AssetDataStrings;
|
||||||
import electrosphere.engine.assetmanager.queue.QueuedTexture;
|
import electrosphere.engine.assetmanager.queue.QueuedTexture;
|
||||||
import electrosphere.game.data.voxel.VoxelData;
|
import electrosphere.game.data.voxel.VoxelData;
|
||||||
import electrosphere.game.data.voxel.VoxelType;
|
import electrosphere.game.data.voxel.VoxelType;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
import electrosphere.renderer.texture.TextureAtlas;
|
||||||
import electrosphere.util.FileUtils;
|
import electrosphere.util.FileUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,7 +37,8 @@ public class InitialAssetLoading {
|
|||||||
*/
|
*/
|
||||||
protected static void loadData(){
|
protected static void loadData(){
|
||||||
|
|
||||||
loadTextureAtlas();
|
loadVoxelTextureAtlas();
|
||||||
|
loadParticleAtlas();
|
||||||
LoggerInterface.loggerEngine.INFO("Finished loading texture atlas");
|
LoggerInterface.loggerEngine.INFO("Finished loading texture atlas");
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -41,7 +46,7 @@ public class InitialAssetLoading {
|
|||||||
/**
|
/**
|
||||||
* Loads the texture atlas
|
* Loads the texture atlas
|
||||||
*/
|
*/
|
||||||
private static void loadTextureAtlas(){
|
private static void loadVoxelTextureAtlas(){
|
||||||
//terrain texture atlas
|
//terrain texture atlas
|
||||||
Globals.profiler.beginCpuSample("createVoxelTextureAtlas");
|
Globals.profiler.beginCpuSample("createVoxelTextureAtlas");
|
||||||
VoxelData data = Globals.gameConfigCurrent.getVoxelData();
|
VoxelData data = Globals.gameConfigCurrent.getVoxelData();
|
||||||
@ -89,6 +94,88 @@ public class InitialAssetLoading {
|
|||||||
Globals.voxelTextureAtlas.setNormal(atlasQueuedTexture.getTexture());
|
Globals.voxelTextureAtlas.setNormal(atlasQueuedTexture.getTexture());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the texture atlas
|
||||||
|
*/
|
||||||
|
private static void loadParticleAtlas(){
|
||||||
|
//terrain texture atlas
|
||||||
|
Globals.profiler.beginCpuSample("create particle texture atlas");
|
||||||
|
int iterator = 0;
|
||||||
|
BufferedImage image = null;
|
||||||
|
TextureAtlas textureAtlas = new TextureAtlas();
|
||||||
|
File particleTextureDirectory = FileUtils.getAssetFile("Textures/particles");
|
||||||
|
File cachedAtlas = FileUtils.getCacheFile("particleAtlas.png");
|
||||||
|
if(cachedAtlas.exists()){
|
||||||
|
try {
|
||||||
|
image = ImageIO.read(Files.newInputStream(cachedAtlas.toPath()));
|
||||||
|
for(File childFile : particleTextureDirectory.listFiles()){
|
||||||
|
if(!childFile.isDirectory()){
|
||||||
|
//put coords in map
|
||||||
|
textureAtlas.putPathCoord(childFile.getName(),iterator);
|
||||||
|
|
||||||
|
//iterate
|
||||||
|
iterator++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new Error("Failed to load texture atlas from cache!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cachedAtlas.getParentFile().mkdirs();
|
||||||
|
image = new BufferedImage(TextureAtlas.ATLAS_DIM, TextureAtlas.ATLAS_DIM, BufferedImage.TYPE_4BYTE_ABGR);
|
||||||
|
Graphics graphics = image.getGraphics();
|
||||||
|
for(File childFile : particleTextureDirectory.listFiles()){
|
||||||
|
if(!childFile.isDirectory()){
|
||||||
|
String texturePath = "Textures/particles/" + childFile.getName();
|
||||||
|
int offX = iterator % TextureAtlas.ELEMENTS_PER_ROW;
|
||||||
|
int offY = iterator / TextureAtlas.ELEMENTS_PER_ROW;
|
||||||
|
try {
|
||||||
|
BufferedImage newType = ImageIO.read(FileUtils.getAssetFile(texturePath));
|
||||||
|
int drawX = TextureAtlas.ATLAS_ELEMENT_DIM * offX;
|
||||||
|
int drawY = TextureAtlas.ATLAS_DIM - TextureAtlas.ATLAS_ELEMENT_DIM - TextureAtlas.ATLAS_ELEMENT_DIM * offY;
|
||||||
|
graphics.drawImage(newType, drawX, drawY, TextureAtlas.ATLAS_ELEMENT_DIM, TextureAtlas.ATLAS_ELEMENT_DIM, null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LoggerInterface.loggerRenderer.ERROR("Texture atlas failed to find texture " + texturePath, e);
|
||||||
|
}
|
||||||
|
//put coords in map
|
||||||
|
textureAtlas.putPathCoord(childFile.getName(),iterator);
|
||||||
|
|
||||||
|
//iterate
|
||||||
|
iterator++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ImageIO.write(image, "png", Files.newOutputStream(cachedAtlas.toPath()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new Error("Failed to save to cache!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
|
||||||
|
//queue to asset manager
|
||||||
|
atlasQueuedTexture = new QueuedTexture(image);
|
||||||
|
Globals.assetManager.queuedAsset(atlasQueuedTexture);
|
||||||
|
|
||||||
|
|
||||||
|
//wait the texture to be loaded
|
||||||
|
while(!atlasQueuedTexture.hasLoaded()){
|
||||||
|
try {
|
||||||
|
TimeUnit.MILLISECONDS.sleep(1);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LoggerInterface.loggerEngine.ERROR("failed to sleep", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//construct texture atlas from buffered image
|
||||||
|
Globals.assetManager.registerTextureToPath(atlasQueuedTexture.getTexture(), AssetDataStrings.TEXTURE_PARTICLE);
|
||||||
|
textureAtlas.setSpecular(atlasQueuedTexture.getTexture());
|
||||||
|
textureAtlas.setNormal(atlasQueuedTexture.getTexture());
|
||||||
|
|
||||||
|
Globals.particleService.setParticleTextureAtlas(textureAtlas);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the queued texture
|
* Gets the queued texture
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -18,6 +18,7 @@ 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;
|
import electrosphere.renderer.actor.instance.InstancedActor;
|
||||||
|
import electrosphere.renderer.texture.TextureAtlas;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Particle component for a client-side particle
|
* Particle component for a client-side particle
|
||||||
@ -122,12 +123,23 @@ public class ClientParticleTree implements BehaviorTree {
|
|||||||
|
|
||||||
//push values to buffer that eventually gets uploaded to gpu
|
//push values to buffer that eventually gets uploaded to gpu
|
||||||
if(instancedActor != null){
|
if(instancedActor != null){
|
||||||
|
TextureAtlas particleTextureAtlas = Globals.particleService.getTextureAtlas();
|
||||||
|
int textureIndex = particleTextureAtlas.getTextureIndex(this.particleData.getTexture());
|
||||||
instancedActor.setAttribute(Globals.particleService.getModelAttrib(), new Matrix4f().translationRotateScale(
|
instancedActor.setAttribute(Globals.particleService.getModelAttrib(), new Matrix4f().translationRotateScale(
|
||||||
new Vector3f((float)parentPosition.x,(float)parentPosition.y,(float)parentPosition.z).sub(cameraPos),
|
new Vector3f((float)parentPosition.x,(float)parentPosition.y,(float)parentPosition.z).sub(cameraPos),
|
||||||
new Quaternionf(rotation),
|
new Quaternionf(rotation),
|
||||||
scale
|
scale
|
||||||
));
|
));
|
||||||
instancedActor.setAttribute(Globals.particleService.getColorAttrib(), new Vector4f((float)this.color.x,(float)this.color.y,(float)this.color.z,1.0f));
|
instancedActor.setAttribute(Globals.particleService.getColorAttrib(), new Vector4f((float)this.color.x,(float)this.color.y,(float)this.color.z,1.0f));
|
||||||
|
|
||||||
|
//when written to buffer, will be written in order w, x, y, z
|
||||||
|
//but gpu will fetch in order x, y, z, w
|
||||||
|
instancedActor.setAttribute(Globals.particleService.getTextureAttrib(), new Vector4f(
|
||||||
|
particleTextureAtlas.getNDCDimension(),
|
||||||
|
particleTextureAtlas.getNDCCoordX(textureIndex),
|
||||||
|
particleTextureAtlas.getNDCCoordY(textureIndex),
|
||||||
|
particleTextureAtlas.getNDCDimension()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -214,7 +214,7 @@ public class RenderUtils {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
particleMesh.setMaterial(new Material(AssetDataStrings.TEXTURE_PARTICLE));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
105
src/main/java/electrosphere/renderer/texture/TextureAtlas.java
Normal file
105
src/main/java/electrosphere/renderer/texture/TextureAtlas.java
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package electrosphere.renderer.texture;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An atlas of texture path -> coordinates on provided texture
|
||||||
|
*/
|
||||||
|
public class TextureAtlas {
|
||||||
|
|
||||||
|
|
||||||
|
//A map of texture path -> coordinates in the atlas texture for its texture
|
||||||
|
Map<String,Integer> pathCoordMap = new HashMap<String,Integer>();
|
||||||
|
|
||||||
|
|
||||||
|
//the actual texture
|
||||||
|
Texture specular;
|
||||||
|
|
||||||
|
//the normal texture
|
||||||
|
Texture normal;
|
||||||
|
|
||||||
|
//the width in pixels of a single texture in the atlas
|
||||||
|
public static final int ATLAS_ELEMENT_DIM = 64;
|
||||||
|
//the width in pixels of the whole atlas texture
|
||||||
|
public static final int ATLAS_DIM = 1024;
|
||||||
|
//number of textures per row in the atlas
|
||||||
|
public static final int ELEMENTS_PER_ROW = ATLAS_DIM / ATLAS_ELEMENT_DIM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts an entry in the path-coord map to map a texture path to a position
|
||||||
|
* @param path the texture's path
|
||||||
|
* @param coord the coordinate in the map
|
||||||
|
*/
|
||||||
|
public void putPathCoord(String path, int coord){
|
||||||
|
pathCoordMap.put(path,coord);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the specular
|
||||||
|
* @param specular the specular
|
||||||
|
*/
|
||||||
|
public void setSpecular(Texture specular){
|
||||||
|
this.specular = specular;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the normal
|
||||||
|
* @param normal the normal
|
||||||
|
*/
|
||||||
|
public void setNormal(Texture normal){
|
||||||
|
this.normal = normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the atlas specular
|
||||||
|
* @return the atlas specular
|
||||||
|
*/
|
||||||
|
public Texture getSpecular(){
|
||||||
|
return specular;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the atlas normal
|
||||||
|
* @return the atlas normal
|
||||||
|
*/
|
||||||
|
public Texture getNormal(){
|
||||||
|
return normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the index in the atlas of a provided texture path
|
||||||
|
* @param texturePath The path to the texture you want the index of
|
||||||
|
* @return the index in the atlas of the texture at the provided texture path
|
||||||
|
*/
|
||||||
|
public int getTextureIndex(String texturePath){
|
||||||
|
return pathCoordMap.containsKey(texturePath) ? pathCoordMap.get(texturePath) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the NDC dimensions of an image in the atlas
|
||||||
|
* @return The NDC dimension
|
||||||
|
*/
|
||||||
|
public float getNDCDimension(){
|
||||||
|
return ATLAS_ELEMENT_DIM / (float)ATLAS_DIM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the NDC x coordinate of an index in the atlas
|
||||||
|
* @param i The index
|
||||||
|
* @return The NDC x coordinate
|
||||||
|
*/
|
||||||
|
public float getNDCCoordX(int i){
|
||||||
|
return (i % ELEMENTS_PER_ROW) * this.getNDCDimension();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the NDC y coordinate of an index in the atlas
|
||||||
|
* @param i The index
|
||||||
|
* @return The NDC y coordinate
|
||||||
|
*/
|
||||||
|
public float getNDCCoordY(int i){
|
||||||
|
return (i / ELEMENTS_PER_ROW) * this.getNDCDimension();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -177,6 +177,17 @@ public class FileUtils {
|
|||||||
File targetFile = new File("./assets" + sanitizedFilePath);
|
File targetFile = new File("./assets" + sanitizedFilePath);
|
||||||
return targetFile;
|
return targetFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a cache file
|
||||||
|
* @param pathName The relative path in the cache folder
|
||||||
|
* @return The file
|
||||||
|
*/
|
||||||
|
public static File getCacheFile(String pathName){
|
||||||
|
String sanitizedFilePath = sanitizeFilePath(pathName);
|
||||||
|
File targetFile = new File("./.cache" + sanitizedFilePath);
|
||||||
|
return targetFile;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a save file
|
* Gets a save file
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user