Skip to content

Commit

Permalink
kram - simd - culler cleanup, added shift and skip bits
Browse files Browse the repository at this point in the history
  • Loading branch information
alecazam committed Oct 11, 2024
1 parent c30e0b0 commit ecf7230
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 29 deletions.
36 changes: 25 additions & 11 deletions libkram/vectormath/bounds234.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ culler::culler(): _planesCount(0) {
}

void culler::update(const float4x4& projView) {
// build a worldspace frustum
// build a worldspace cameraa volume
// https://fgiesen.wordpress.com/2010/10/17/view-frustum-culling/
// but don't test farZ plane if infFarZ

Expand Down Expand Up @@ -50,7 +50,7 @@ void culler::update(const float4x4& projView) {
// with w=0 for points at infinity, this just falls out of the usual
// point vs plane test, where you dot the homogeneous point against the plane equation.

// generate 8 corners of frustum from the inverse
// generate 8 corners of camera volume from the inverse
float4x4 projViewInv = inverse(projView); // TODO: can pass down
float nearClip = 1;

Expand Down Expand Up @@ -119,28 +119,42 @@ bool culler::cullSphere(float4 sphere) const {
return count == _planesCount;
}

void culler::cullBoxes(const float3* boxes, int count, uint8_t* results) const {
void culler::cullBoxes(const float3* boxes, int count, uint8_t shift, uint8_t* results) const {
// box array is 2x count
uint8_t bit = (1 << shift);
uint8_t skipBit = (1 << 7);

for (int i = 0; i < count; ++i) {
uint8_t& res8 = results[i];
if ((res8 & skipBit) != 0)
continue;

float3 min = boxes[2*i];
float3 max = boxes[2*i+1];

if (cullBox(min, max))
results[i] |= 1;
res8 |= bit;
}
}

void culler::cullSpheres(const float4* sphere, int count, uint8_t* results) const {
void culler::cullSpheres(const float4* sphere, int count, uint8_t shift, uint8_t* results) const {
uint8_t bit = (1 << shift);
uint8_t skipBit = (1 << 7);

for (int i = 0; i < count; ++i) {
uint8_t& res8 = results[i];
if ((res8 & skipBit) != 0)
continue;

if (cullSphere(sphere[i]))
results[i] |= 1;
res8 |= bit;
}
}

bool culler::isFrustumInBox(bbox box) const {
bool culler::isCameraInBox(bbox box) const {
// See if all 8 verts of the frustum are in the box.
// This becomes a false negative for non-inf far (skips box while inside)
const float3* corners = frustumCorners();
const float3* corners = cameraCorners();

int3 count = 0;
for (int i = 0; i < 8; ++i) {
Expand All @@ -153,10 +167,10 @@ bool culler::isFrustumInBox(bbox box) const {
return all(count == (int3)-8);
}

bool culler::isFrustumOutsideBox(bbox box) const {
// See if all 8 verts of the frustum are outside box.
bool culler::isCameraOutsideBox(bbox box) const {
// See if all 8 verts of the camera are outside box.
// This becomes a false positive (draws box even though outside)
const float3* corners = frustumCorners();
const float3* corners = cameraCorners();

int3 countMin = 0;
int3 countMax = 0;
Expand Down
42 changes: 24 additions & 18 deletions libkram/vectormath/bounds234.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,38 +80,40 @@ struct culler {

void update(const float4x4& projView);

// TODO: should pass bitmask instead of uint8_t array
// caller must zero the results array, and visible state sets only low bit

void cullBoxes(const float3* boxes, int count, uint8_t* results) const;
void cullSpheres(const float4* sphere, int count, uint8_t* results) const;

// can use the helper types instead
bool cullSphere(float4 sphere) const;
bool cullBox(float3 min, float3 max) const;

// can use the helper types instead
void cullBoxes(const bbox* boxes, int count, uint8_t* results) const {
cullBoxes((const float3*)boxes, count, results);
}
bool cullBoxes(const bbox& box) const {
bool cullBox(const bbox& box) const {
return cullBox(box.min, box.max);
}
void cullSpheres(const bsphere* spheres, int count, uint8_t* results) const {
cullSpheres((const float4*)spheres, count, results);
}
bool cullSphere(const bsphere& sphere) const {
return cullSphere(sphere.centerRadius);
}

// should probably move these
// Caller must zero the results array, and visible state sets only low bit
// These store a bit (with shift) in the results array.
// If high bit is set in results, then test is skipped.
void cullBoxes(const float3* boxes, int count, uint8_t shift, uint8_t* results) const;
void cullSpheres(const float4* sphere, int count, uint8_t shift, uint8_t* results) const;

void cullBoxes(const bbox* boxes, int count, uint8_t shift, uint8_t* results) const {
cullBoxes((const float3*)boxes, count, shift, results);
}
void cullSpheres(const bsphere* spheres, int count, uint8_t shift, uint8_t* results) const {
cullSpheres((const float4*)spheres, count, shift, results);
}

// move these out?
static bsphere transformSphereTRS(bsphere sphere, const float4x4& modelTfm);
static bbox transformBoxTRS(bbox box, const float4x4& modelTfm);

// bbox corners
void boxCorners(bbox box, float3 pt[8]) const;
void boxCorners(bbox box, float4 pt[8]) const;

bool isFrustumInBox(bbox box) const;
bool isFrustumOutsideBox(bbox box) const;
bool isCameraInBox(bbox box) const;
bool isCameraOutsideBox(bbox box) const;

// Camera corners in world space
const float3* cameraCorners() const {
Expand All @@ -124,14 +126,18 @@ struct culler {
int cameraPlanesCount() const { return _planesCount; }

private:
// camera planes in world space
float4 _planes[6];

// This won't work if SIMD_INT is not defined.
#if SIMD_INT
// cached tests of which planes are positive/negative
int4 _selectionMasks[6];
#endif

uint32_t _planesCount;

// 8 corners of frustum
// 8 corners of camera volume
float4 _corners[8];
};

Expand Down

0 comments on commit ecf7230

Please sign in to comment.