2020-11-28 16:54:41 +02:00

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);
}
*/