diff --git a/assets/Data/game/blockTypes.json b/assets/Data/game/blockTypes.json new file mode 100644 index 00000000..dc98d10f --- /dev/null +++ b/assets/Data/game/blockTypes.json @@ -0,0 +1,13 @@ +{ + "types" : [ + { + "id" : 0, + "name" : "air" + }, + { + "id" : 1, + "name" : "brick", + "texture" : "/Textures/Ground/Dirt2_256.png" + } + ] +} \ No newline at end of file diff --git a/assets/Shaders/entities/block/block.fs b/assets/Shaders/entities/block/block.fs new file mode 100644 index 00000000..52ca6a35 --- /dev/null +++ b/assets/Shaders/entities/block/block.fs @@ -0,0 +1,289 @@ +#version 450 core + +//texture defines +#define ATLAS_ELEMENT_DIM 256.0 +#define ATLAS_DIM 8192.0 +#define ATLAS_EL_PER_ROW 32 +#define ATLAS_NORMALIZED_ELEMENT_WIDTH 0.031 //within the single texture within the atlas, we use this so we never go over the end of the texture +#define ATLAS_NORMALIZED_ELEMENT_WIDTH_FULL 0.03125 //used to properly shift from texture to texture in the atlas + + +/** +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 uv; +in vec4 FragPosLightSpace; +in flat int samplerIndexVec; //the indices in the atlas of textures to sample + + +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); +vec3 getColor(vec2 uv, vec3 normal, int samplerIndexVec, Material material); + +void main(){ + vec3 norm = normalize(Normal); + vec3 viewDir = normalize(viewPos - FragPos); + + //grab light intensity + vec3 lightIntensity = vec3(calcLightIntensityTotal(norm)); + + //get color of base texture + vec3 textureColor = getColor(uv, norm, samplerIndexVec, material); + + //shadow + float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), -norm); + + // + //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, norm, 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); + + //this final calculation is for transparency + FragColor = vec4(finalColor, 1); +} + + +/** + * The function that gets the texture color based on the triplanar texture mapping and the voxel type at each point along the vert. + * See the triplanar mapping wiki article for an explanation of math involved. + */ +vec3 getColor(vec2 uv, vec3 normal, int samplerIndexVec, Material material){ + + //the uv of the texture clamped within the atlas + vec2 actualUv = vec2( + (fract(uv.x) * ATLAS_NORMALIZED_ELEMENT_WIDTH) + (mod(samplerIndexVec,ATLAS_EL_PER_ROW) * ATLAS_NORMALIZED_ELEMENT_WIDTH_FULL), + (fract(uv.y) * ATLAS_NORMALIZED_ELEMENT_WIDTH) + (round(samplerIndexVec / ATLAS_EL_PER_ROW) * ATLAS_NORMALIZED_ELEMENT_WIDTH_FULL) + ); + //albedo for the X texture + vec3 color = texture(material.diffuse, actualUv).rgb; + + + return color; +} + +// +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 clamp(1.0 - shadow, 0.0, 0.7); +} \ No newline at end of file diff --git a/assets/Shaders/entities/block/block.vs b/assets/Shaders/entities/block/block.vs new file mode 100644 index 00000000..861f3f16 --- /dev/null +++ b/assets/Shaders/entities/block/block.vs @@ -0,0 +1,58 @@ +//Vertex Shader +#version 330 core + +//defines +#define TEXTURE_MAP_SCALE 1.0 +#define MODEL_TOTAL_DIM 16.0 + + +//input buffers +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 4) in vec2 aTex; +layout (location = 5) in int samplerIndices; + + +//coordinate space transformation matrices +uniform mat4 transform; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; +uniform mat4 lightSpaceMatrix; + + + +//output buffers +out vec3 Normal; +out vec3 FragPos; +out vec3 ViewFragPos; +out vec2 uv; +out vec4 FragPosLightSpace; +flat out int samplerIndexVec; + + + + +void main() { + //normalize posiiton and normal + vec4 FinalVertex = vec4(aPos, 1.0); + vec4 FinalNormal = vec4(aNormal, 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; + uv = aTex; + + //pass through what atlas'd textures to sample + samplerIndexVec = samplerIndices; + + + //shadow map stuff + FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0); + + + //set final position with opengl space + gl_Position = projection * view * model * FinalVertex; +} diff --git a/buildNumber.properties b/buildNumber.properties index d19bcd3b..80198752 100644 --- a/buildNumber.properties +++ b/buildNumber.properties @@ -1,3 +1,3 @@ #maven.buildNumber.plugin properties file -#Sat Nov 23 20:49:19 EST 2024 -buildNumber=403 +#Sun Nov 24 15:46:03 EST 2024 +buildNumber=404 diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index d7ed047b..d249ca18 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1154,6 +1154,7 @@ Convert PhysicsEntityUtils to use generic interface to load tri geom rigid bodie (11/24/2024) Fix winding order on block meshes +Add texture atlasing to blocks # TODO diff --git a/src/main/java/electrosphere/engine/Globals.java b/src/main/java/electrosphere/engine/Globals.java index 9273c2b0..7de1d0dd 100644 --- a/src/main/java/electrosphere/engine/Globals.java +++ b/src/main/java/electrosphere/engine/Globals.java @@ -299,6 +299,7 @@ public class Globals { public static VisualShader defaultMeshShader; public static VisualShader terrainShaderProgram; + public static VisualShader blockShader; // // Particle stuff @@ -365,7 +366,7 @@ public class Globals { public static ClientDrawCellManager clientDrawCellManager; public static VoxelTextureAtlas voxelTextureAtlas = new VoxelTextureAtlas(); public static ClientBlockCellManager clientBlockCellManager; - public static BlockTextureAtlas blockTextureAtlas = null; + public static BlockTextureAtlas blockTextureAtlas = new BlockTextureAtlas(); //fluid cell manager public static FluidCellManager fluidCellManager; @@ -649,6 +650,7 @@ public class Globals { defaultMeshShader = VisualShader.smart_assemble_shader(false,true); //init terrain shader program terrainShaderProgram = VisualShader.loadSpecificShader("/Shaders/entities/terrain2/terrain2.vs", "/Shaders/entities/terrain2/terrain2.fs"); + blockShader = VisualShader.loadSpecificShader("/Shaders/entities/block/block.vs", "/Shaders/entities/block/block.fs"); //init fluid shader program FluidChunkModelGeneration.fluidChunkShaderProgram = VisualShader.loadSpecificShader("/Shaders/entities/fluid2/fluid2.vs", "/Shaders/entities/fluid2/fluid2.fs"); //init models diff --git a/src/main/java/electrosphere/engine/loadingthreads/InitialAssetLoading.java b/src/main/java/electrosphere/engine/loadingthreads/InitialAssetLoading.java index 63d45fa0..773141dc 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/InitialAssetLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/InitialAssetLoading.java @@ -9,10 +9,13 @@ import java.util.concurrent.TimeUnit; import javax.imageio.ImageIO; +import electrosphere.client.block.cells.BlockTextureAtlas; import electrosphere.client.terrain.cells.VoxelTextureAtlas; import electrosphere.engine.Globals; import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.queue.QueuedTexture; +import electrosphere.game.data.block.BlockData; +import electrosphere.game.data.block.BlockType; import electrosphere.game.data.voxel.VoxelData; import electrosphere.game.data.voxel.VoxelType; import electrosphere.logger.LoggerInterface; @@ -37,14 +40,15 @@ public class InitialAssetLoading { */ protected static void loadData(){ - loadVoxelTextureAtlas(); - loadParticleAtlas(); + InitialAssetLoading.loadVoxelTextureAtlas(); + InitialAssetLoading.loadBlockTextureAtlas(); + InitialAssetLoading.loadParticleAtlas(); LoggerInterface.loggerEngine.INFO("Finished loading texture atlas"); } /** - * Loads the texture atlas + * Loads the voxel texture atlas */ private static void loadVoxelTextureAtlas(){ //terrain texture atlas @@ -95,7 +99,58 @@ public class InitialAssetLoading { } /** - * Loads the texture atlas + * Loads the block texture atlas + */ + private static void loadBlockTextureAtlas(){ + //terrain texture atlas + Globals.profiler.beginCpuSample("createBlockTextureAtlas"); + BlockData data = Globals.gameConfigCurrent.getBlockData(); + int iterator = 0; + BufferedImage image = new BufferedImage(BlockTextureAtlas.ATLAS_DIM, BlockTextureAtlas.ATLAS_DIM, BufferedImage.TYPE_4BYTE_ABGR); + Graphics graphics = image.getGraphics(); + for(BlockType type : data.getTypes()){ + if(type.getTexture() != null){ + int offX = iterator % BlockTextureAtlas.ELEMENTS_PER_ROW; + int offY = iterator / BlockTextureAtlas.ELEMENTS_PER_ROW; + try { + BufferedImage newType = ImageIO.read(FileUtils.getAssetFile(type.getTexture())); + int drawX = BlockTextureAtlas.ATLAS_ELEMENT_DIM * offX; + int drawY = BlockTextureAtlas.ATLAS_DIM - BlockTextureAtlas.ATLAS_ELEMENT_DIM - BlockTextureAtlas.ATLAS_ELEMENT_DIM * offY; + graphics.drawImage(newType, drawX, drawY, null); + } catch (IOException e) { + LoggerInterface.loggerRenderer.ERROR("Texture atlas failed to find texture " + type.getTexture(), e); + } + //put coords in map + Globals.blockTextureAtlas.putTypeCoord(type.getId(),iterator); + + //iterate + iterator++; + } + } + 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.blockTextureAtlas.setSpecular(atlasQueuedTexture.getTexture()); + Globals.blockTextureAtlas.setNormal(atlasQueuedTexture.getTexture()); + } + + /** + * Loads the particle texture atlas */ private static void loadParticleAtlas(){ //terrain texture atlas diff --git a/src/main/java/electrosphere/game/data/Config.java b/src/main/java/electrosphere/game/data/Config.java index 6a4a4ba6..f8cf9e51 100644 --- a/src/main/java/electrosphere/game/data/Config.java +++ b/src/main/java/electrosphere/game/data/Config.java @@ -5,6 +5,7 @@ import java.util.List; import electrosphere.game.data.audio.SurfaceAudioCollection; import electrosphere.game.data.biome.BiomeTypeMap; +import electrosphere.game.data.block.BlockData; import electrosphere.game.data.common.CommonEntityLoader; import electrosphere.game.data.common.CommonEntityMap; import electrosphere.game.data.common.CommonEntityType; @@ -45,6 +46,11 @@ public class Config { //data about every voxel type VoxelData voxelData; + /** + * The block data + */ + BlockData blockData; + //the hints that are defined HintDefinition hintData; @@ -86,6 +92,7 @@ public class Config { config.symbolMap = FileUtils.loadObjectFromAssetPath("Data/game/symbolism.json", SymbolMap.class); config.raceMap = FileUtils.loadObjectFromAssetPath("Data/game/races.json", RaceMap.class); config.voxelData = FileUtils.loadObjectFromAssetPath("Data/game/voxelTypes.json", VoxelData.class); + config.blockData = FileUtils.loadObjectFromAssetPath("Data/game/blockTypes.json", BlockData.class); config.projectileTypeHolder = FileUtils.loadObjectFromAssetPath("Data/entity/projectile.json", ProjectileTypeHolder.class); config.hintData = FileUtils.loadObjectFromAssetPath("Data/tutorial/hints.json", HintDefinition.class); config.surfaceAudioCollection = FileUtils.loadObjectFromAssetPath("Data/audio/surface.json", SurfaceAudioCollection.class); @@ -250,6 +257,14 @@ public class Config { return voxelData; } + /** + * Gets the block data + * @return The block data + */ + public BlockData getBlockData(){ + return blockData; + } + /** * The tutorial hints data * @return The hints diff --git a/src/main/java/electrosphere/game/data/block/BlockData.java b/src/main/java/electrosphere/game/data/block/BlockData.java new file mode 100644 index 00000000..41705cf2 --- /dev/null +++ b/src/main/java/electrosphere/game/data/block/BlockData.java @@ -0,0 +1,47 @@ +package electrosphere.game.data.block; + +import java.util.Set; + +/** + * A list of all block types in game + */ +public class BlockData { + //The set of all voxel types + Set types; + + /** + * Gets all block types + * @return The set of all block types + */ + public Set getTypes(){ + return types; + } + + /** + * Gets the block type by its name, or null if that type does not exist + * @param name The name of the block type + * @return The block type or null + */ + public BlockType getTypeFromName(String name){ + for(BlockType type : types){ + if(type.name.contains(name)){ + return type; + } + } + return null; + } + + /** + * Gets the block type by its id, or null if that type does not exist + * @param id The id of the block type + * @return The block type or null + */ + public BlockType getTypeFromId(int id){ + for(BlockType type : types){ + if(type.id == id){ + return type; + } + } + return null; + } +} diff --git a/src/main/java/electrosphere/game/data/block/BlockType.java b/src/main/java/electrosphere/game/data/block/BlockType.java new file mode 100644 index 00000000..8755d8c8 --- /dev/null +++ b/src/main/java/electrosphere/game/data/block/BlockType.java @@ -0,0 +1,37 @@ +package electrosphere.game.data.block; + +/** + * Data about a particular type of block + */ +public class BlockType { + //the id of this block type + int id; + //the name of the type + String name; + //the texture for the block type + String texture; + + /** + * Gets the id of the block type + * @return The id + */ + public int getId(){ + return id; + } + + /** + * Gets the name of the block type + * @return The name + */ + public String getName(){ + return name; + } + + /** + * Gets the texture of this block types + * @return the texture + */ + public String getTexture(){ + return texture; + } +} diff --git a/src/main/java/electrosphere/renderer/meshgen/BlockMeshgen.java b/src/main/java/electrosphere/renderer/meshgen/BlockMeshgen.java index fcd49d1e..c466e600 100644 --- a/src/main/java/electrosphere/renderer/meshgen/BlockMeshgen.java +++ b/src/main/java/electrosphere/renderer/meshgen/BlockMeshgen.java @@ -14,6 +14,7 @@ import org.lwjgl.opengl.GL40; import electrosphere.client.block.BlockChunkData; import electrosphere.engine.Globals; import electrosphere.entity.state.collidable.TriGeomData; +import electrosphere.renderer.model.Material; import electrosphere.renderer.model.Mesh; import electrosphere.renderer.model.Model; @@ -51,6 +52,16 @@ public class BlockMeshgen { 4, 5, 7 }; + /** + * Position of the sampler data in the buffer + */ + static final int SAMPLER_SHADER_POSITION = 5; + + /** + * The size of the sampler data per-vertex + */ + static final int SAMPLER_DATA_SIZE = 1; + /** * Calculates the quad meshes for the provided chunk data @@ -88,6 +99,7 @@ public class BlockMeshgen { currentQuad.z = z; currentQuad.w = 1; currentQuad.h = 1; + currentQuad.type = chunkData.getType(x, y, z); } else { continue; } @@ -103,10 +115,12 @@ public class BlockMeshgen { * @param normals The list of normals to store into * @param uvs The list of uvs to store into * @param indices The list of indices to store into + * @param samplers The sampler for a given vertex * @param quad The quad * @param depth The depth of the box + * @param blockType The type of block */ - protected static void meshifyBox(List verts, List normals, List uvs, List indices, QuadMesh quad, int depth){ + protected static void meshifyBox(List verts, List normals, List uvs, List indices, List samplers, QuadMesh quad, int depth, int blockType){ // //face 1 // @@ -291,6 +305,7 @@ public class BlockMeshgen { List normals = new LinkedList(); List uvs = new LinkedList(); List indices = new LinkedList(); + List samplers = new LinkedList(); //the texture to sample for this quad //sort Collections.sort(quadMeshes); @@ -307,7 +322,7 @@ public class BlockMeshgen { if(quad1.x == quad2.x && quad1.y == quad2.y && quad1.w == quad2.w && quad1.h == quad2.h && quad1.z + zEnd == quad2.z){ zEnd++; } else { - BlockMeshgen.meshifyBox(verts,normals,uvs,indices,quad1,zEnd); + BlockMeshgen.meshifyBox(verts,normals,uvs,indices,samplers,quad1,zEnd,quad1.type); quad1 = quad2; zEnd = 1; break; @@ -316,7 +331,7 @@ public class BlockMeshgen { i = i + zEnd; } if(quad1 != null){ - BlockMeshgen.meshifyBox(verts,normals,uvs,indices,quad1,zEnd); + BlockMeshgen.meshifyBox(verts,normals,uvs,indices,samplers,quad1,zEnd,quad1.type); } // @@ -363,6 +378,14 @@ public class BlockMeshgen { rVal.uvBuffer = BufferUtils.createFloatBuffer(rVal.uvs.length); rVal.uvBuffer.put(rVal.uvs); + //samplers + rVal.samplers = new int[samplers.size()]; + for(int i = 0; i < samplers.size(); i++){ + rVal.samplers[i] = samplers.get(i); + } + rVal.samplerBuffer = BufferUtils.createIntBuffer(rVal.samplers.length); + rVal.samplerBuffer.put(rVal.samplers); + return rVal; } @@ -387,6 +410,7 @@ public class BlockMeshgen { FloatBuffer normalArrayBufferData = meshData.normalBuffer; FloatBuffer textureArrayBufferData = meshData.uvBuffer; IntBuffer elementArrayBufferData = meshData.faceBuffer; + IntBuffer samplerArrayBufferData = meshData.samplerBuffer; @@ -416,6 +440,11 @@ public class BlockMeshgen { elementArrayBufferData.flip(); mesh.bufferFaces(elementArrayBufferData, elementCount); } + //buffer sampler indices + if(samplerArrayBufferData != null && samplerArrayBufferData.position() > 0){ + samplerArrayBufferData.flip(); + mesh.bufferCustomIntAttribArray(samplerArrayBufferData, SAMPLER_DATA_SIZE, SAMPLER_SHADER_POSITION); + } } catch (NullPointerException ex){ ex.printStackTrace(); } @@ -448,13 +477,13 @@ public class BlockMeshgen { Mesh m = BlockMeshgen.generateBlockMesh(meshData); //construct the material for the chunk - // Material groundMat = new Material(); - // groundMat.setTexturePointer(Globals.defaultMeshShader); - // groundMat.setNormalTexturePointer(atlas.getNormal().getTexturePointer()); - // m.setMaterial(groundMat); + Material groundMat = new Material(); + groundMat.setTexturePointer(Globals.blockTextureAtlas.getSpecular().getTexturePointer()); + groundMat.setNormalTexturePointer(Globals.blockTextureAtlas.getNormal().getTexturePointer()); + m.setMaterial(groundMat); //shader logic - m.setShader(Globals.defaultMeshShader); + m.setShader(Globals.blockShader); m.setParent(rVal); rVal.getMeshes().add(m); @@ -476,11 +505,14 @@ public class BlockMeshgen { int[] faceElements; //UVs float[] uvs; + //The samplers for each quad + int[] samplers; FloatBuffer vertBuffer; FloatBuffer normalBuffer; IntBuffer faceBuffer; FloatBuffer uvBuffer; + IntBuffer samplerBuffer; @Override public float[] getVertices() { @@ -501,13 +533,15 @@ public class BlockMeshgen { int z; int w; int h; + int type; public QuadMesh(){} - public QuadMesh(int x, int y, int z, int w, int h){ + public QuadMesh(int x, int y, int z, int w, int h, int type){ this.x = x; this.y = y; this.z = z; this.w = w; this.h = h; + this.type = type; } @Override diff --git a/src/test/java/electrosphere/renderer/meshgen/BlockMeshgenTests.java b/src/test/java/electrosphere/renderer/meshgen/BlockMeshgenTests.java index 88cb0b3c..a09e5ca8 100644 --- a/src/test/java/electrosphere/renderer/meshgen/BlockMeshgenTests.java +++ b/src/test/java/electrosphere/renderer/meshgen/BlockMeshgenTests.java @@ -28,7 +28,7 @@ public class BlockMeshgenTests { //expected data QuadMesh[] expectedData = new QuadMesh[]{ - new QuadMesh(0,0,0,1,1), + new QuadMesh(0,0,0,1,1,1), }; //setup data @@ -65,7 +65,7 @@ public class BlockMeshgenTests { public void test_fillQuadMeshes_2(){ //expected data QuadMesh[] expectedData = new QuadMesh[]{ - new QuadMesh(0,0,0,1,2), + new QuadMesh(0,0,0,1,2,1), }; //setup data @@ -103,7 +103,7 @@ public class BlockMeshgenTests { public void test_fillQuadMeshes_3(){ //expected data QuadMesh[] expectedData = new QuadMesh[]{ - new QuadMesh(0,0,0,2,2), + new QuadMesh(0,0,0,2,2,1), }; //setup data @@ -143,8 +143,8 @@ public class BlockMeshgenTests { public void test_fillQuadMeshes_4(){ //expected data QuadMesh[] expectedData = new QuadMesh[]{ - new QuadMesh(0,0,0,1,1), - new QuadMesh(0,2,0,1,1), + new QuadMesh(0,0,0,1,1,1), + new QuadMesh(0,2,0,1,1,1), }; //setup data @@ -236,10 +236,11 @@ public class BlockMeshgenTests { List normals = new LinkedList(); List uvs = new LinkedList(); List indices = new LinkedList(); - QuadMesh quad = new QuadMesh(0, 0, 0, 1, 1); + List samplers = new LinkedList(); + QuadMesh quad = new QuadMesh(0, 0, 0, 1, 1,1); //call - BlockMeshgen.meshifyBox(verts, normals, uvs, indices, quad, 1); + BlockMeshgen.meshifyBox(verts, normals, uvs, indices, samplers, quad, 1, 1); //error check result @@ -296,10 +297,11 @@ public class BlockMeshgenTests { List normals = new LinkedList(); List uvs = new LinkedList(); List indices = new LinkedList(); - QuadMesh quad = new QuadMesh(0, 0, 0, 1, 1); + List samplers = new LinkedList(); + QuadMesh quad = new QuadMesh(0, 0, 0, 1, 1, 1); //call - BlockMeshgen.meshifyBox(verts, normals, uvs, indices, quad, 1); + BlockMeshgen.meshifyBox(verts, normals, uvs, indices, samplers, quad, 1, 1); //error check result @@ -354,10 +356,11 @@ public class BlockMeshgenTests { List normals = new LinkedList(); List uvs = new LinkedList(); List indices = new LinkedList(); - QuadMesh quad = new QuadMesh(0, 0, 0, 1, 1); + List samplers = new LinkedList(); + QuadMesh quad = new QuadMesh(0, 0, 0, 1, 1, 1); //call - BlockMeshgen.meshifyBox(verts, normals, uvs, indices, quad, 1); + BlockMeshgen.meshifyBox(verts, normals, uvs, indices, samplers, quad, 1, 1); //error check result