146 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| #pragma kernel CSCullIndividual
 | |
| #pragma kernel CSCullCell
 | |
| 
 | |
| struct GrassElement {
 | |
|     float3 position;
 | |
|     float rotation;
 | |
|     float size;
 | |
|     float colorBlend;//0-1
 | |
|     };
 | |
| 
 | |
| struct grassCell {
 | |
|     uint grassElementIndexes[512];//map to grass elements
 | |
|     };
 | |
| 
 | |
| //struct grassOcclusionCell {
 | |
| //    uint grassCellIndex;
 | |
| //    uint visibleCellIndexes[2048];//Map to occlusion cells
 | |
| //    };
 | |
| 
 | |
| //General
 | |
| uint grassCount;
 | |
| float2 distanceBounts;//Start, end
 | |
| Texture2D<float4> ditherTex;
 | |
| int ditherTexSizeX;
 | |
| float ditherSize;
 | |
| 
 | |
| //Input
 | |
| StructuredBuffer<GrassElement> grassBuffer;
 | |
| 
 | |
| //Frustrum culling
 | |
| float3 cameraPos;
 | |
| float4x3 cameraFrustumNormals;
 | |
| 
 | |
| //settings
 | |
| int doOcclusion;
 | |
| 
 | |
| //Cells
 | |
| uint grassCellCount;
 | |
| uint grassCellSize;
 | |
| StructuredBuffer<grassCell> grassCellBuffer;
 | |
| 
 | |
| //Occlusion culling
 | |
| //StructuredBuffer<grassOcclusionCell> grassOcclusionBuffer;
 | |
| 
 | |
| //Output
 | |
| AppendStructuredBuffer<uint> outGrassBuffer;
 | |
| AppendStructuredBuffer<uint> outCellIndexBuffer;
 | |
| 
 | |
| bool Is3DDither (float dist, float2 pos) {
 | |
|     float distAmount = 1 - (dist-distanceBounts.x)/(distanceBounts.y-distanceBounts.x);//0-1
 | |
|     float2 relativePos = pos/ditherSize;
 | |
|     float2 positivePos = float2(relativePos.x*sign(relativePos.x),relativePos.y*sign(relativePos.y));
 | |
|     float2 repeatingPos = float2(fmod(positivePos.x,ditherTexSizeX),fmod(positivePos.y,ditherTexSizeX));
 | |
|     float dit = ditherTex[repeatingPos].x;
 | |
|     return distAmount - dit > 0;
 | |
|     }
 | |
| 
 | |
| [numthreads(16,16,4)]
 | |
| void CSCullIndividual (uint index : SV_GroupIndex, uint3 group : SV_GroupID) {//This only does frustrum culling
 | |
|     //1. get index
 | |
|     uint realIndex = index + 1024 * group.x;//id.x + id.y group.x + id.z group.x * group.y
 | |
| 
 | |
|     //2. index valid?
 | |
|     if(realIndex < grassCount) {
 | |
|         GrassElement data = grassBuffer[realIndex];
 | |
|         float3 pos = data.position;
 | |
| 
 | |
|         float3 posFromCamera = pos - cameraPos;
 | |
|         float scale = data.size;
 | |
| 
 | |
|         //3. frustrum culling
 | |
|         if( (dot(cameraFrustumNormals[0], posFromCamera) > -scale) &&
 | |
|             (dot(cameraFrustumNormals[1], posFromCamera) > -scale) &&
 | |
|             (dot(cameraFrustumNormals[2], posFromCamera) > -scale) &&
 | |
|             (dot(cameraFrustumNormals[3], posFromCamera) > -scale) ){
 | |
|             //3D dither culling (includes dist culling)
 | |
|             float dist = length(posFromCamera);
 | |
|             if(Is3DDither(dist,pos.xz)) {
 | |
|                 outGrassBuffer.Append(realIndex);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| [numthreads(8,8,1)]
 | |
| void CSCullCell (uint index : SV_GroupIndex, uint3 group : SV_GroupID) {//This does frustrum and occlusion culling on cells
 | |
|     //1. get index
 | |
|     uint realIndex = index + 8*8*group.x;
 | |
|     //2. index valid?
 | |
| 
 | |
|     if(realIndex < grassCellCount) {
 | |
|         //outGrassBuffer.Append(realIndex);
 | |
|         //outCellIndexBuffer.Append(realIndex);
 | |
|         grassCell cell = grassCellBuffer[realIndex];
 | |
|         
 | |
|         //for(int i=0;i<512;i++) {
 | |
|         //    int k = cell.grassElementIndexes[i];
 | |
|         //    if(k != 0)outGrassBuffer.Append(k);
 | |
|         //    }
 | |
|         
 | |
|         //Doing frustrum check with ranodom element from cell
 | |
|         float3 pos = grassBuffer[cell.grassElementIndexes[0]].position;
 | |
|         
 | |
|         float3 posFromCamera = pos - cameraPos;
 | |
|         float scale = grassCellSize;
 | |
|         
 | |
|         //3. frustrum culling
 | |
|         if( (dot(cameraFrustumNormals[0], posFromCamera) > -scale) &&
 | |
|             (dot(cameraFrustumNormals[1], posFromCamera) > -scale) &&
 | |
|             (dot(cameraFrustumNormals[2], posFromCamera) > -scale) &&
 | |
|             (dot(cameraFrustumNormals[3], posFromCamera) > -scale) ){
 | |
| 
 | |
|             if(length(posFromCamera) <= distanceBounts.y) {//Dist check
 | |
|                 if(doOcclusion == 1) {
 | |
|                     //TODO see if this chunk is visible from current chunk
 | |
|                     //TODO if yes then append chunk grass indexes
 | |
|                     }
 | |
|                 else {
 | |
|                     outCellIndexBuffer.Append(realIndex);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| //group -> thread
 | |
| //SV_GroupThreadID = current threads num.xyz
 | |
| //SV_GroupIndex = num.x * num.y * num.z;
 | |
| //SV_GroupID = current gorup indices
 | |
| 
 | |
| 
 | |
| /* This works for some reason
 | |
| [numthreads(8,8,8)]
 | |
| void Converter (uint callIndex : SV_GroupIndex, uint3 groupID : SV_GroupID) {
 | |
|     uint realIndex = groupID.x + groupID.y + groupID.z;
 | |
| 
 | |
|     uint cellIndex = grassCellIndexBuffer[realIndex];
 | |
| 
 | |
|     grassCell cell = grassCellBuffer[ cellIndex ];
 | |
| 
 | |
|     int elementIndex = callIndex;//Correct
 | |
|     uint objIndex = cell.grassElementIndexes[elementIndex];
 | |
|     if(objIndex != 0) outGrassBuffer.Append(objIndex);
 | |
|     
 | |
|     }
 | |
| */ |