cocos2d/cocos2d-objc

Vertices pages boundary overlap

AlexCP11 opened this issue · 0 comments

There is an issue related to vertices pages boundary overlap. Result is extra random triangles or missed triangles. Issue reproduced on my devices iPad Mini (iOS 15.7.1), iPhone 7+ (iOS 15.7.5) and all Simulators (iOS 13.7, 14.2, 16.4).

Simplified sample code. Triangles should fill-up all node to make glitches easy visible. 5 vertices per iteration used to guarantee pages overlap.

- (void) draw:(CCRenderer *)renderer transform:(const GLKMatrix4 *)transform
{
    int verticesCount = 65535*2+10; // to make two pages overlaps
    int trianglesDrawsCount = (verticesCount/5); 
    
    GLKVector4 redColor = [CCColor colorWithRed:1. green:0. blue:0. alpha:1.].glkVector4;
    CGFloat x,y,d;
    int trianlgesPerRow = 132;
    d = <triangle size to fill-up node with triangles>;

    CGFloat vertexArray[10];
    CGPoint points[5];
    for (int trianglesDraw=0; trianglesDraw<trianglesDrawsCount; trianglesDraw++) {
        x = d*(trianglesDraw%trianlgesPerRow);
        y = d*(trianglesDraw/trianlgesPerRow);
        
        vertexArray[0] = x;
        vertexArray[1] = y;
        vertexArray[2] = x+d;
        vertexArray[3] = y;
        vertexArray[4] = x+d;
        vertexArray[5] = y+d;
        
        vertexArray[6] = x;
        vertexArray[7] = y+d;
        vertexArray[8] = x+d;
        vertexArray[9] = y+d;

        CCRenderBuffer buffer = [renderer enqueueTriangles:2 andVertexes:5 withState:self.renderState globalSortOrder:0];

        for (int i=0; i<5; ++i) {
            points[i] = ccp(vertexArray[2*i], vertexArray[2*i+1]);
            CCRenderBufferSetVertex(buffer, i, CCVertexApplyTransform((CCVertex){{points[i].x, points[i].y, 0, 1}, {0, 0}, {0, 0}, redColor}, transform));
        }

        CCRenderBufferSetTriangle(buffer, 0, 0, 1, 2);
        CCRenderBufferSetTriangle(buffer, 1, 0, 3, 4);
    }
}

Result is in attachment.
pagesoverlap_issue

Take a look into CCNoARC.m file. Method CCRenderer::enqueueLines:andVertexes:withState:globalSortOrder:

-(CCRenderBuffer)enqueueTriangles:(NSUInteger)triangleCount andVertexes:(NSUInteger)vertexCount withState:(CCRenderState *)renderState globalSortOrder:(NSInteger)globalSortOrder;
{
	// Need to record the first vertex or element index before pushing more vertexes.
	NSUInteger firstVertex = _buffers->_vertexBuffer->_count;
	NSUInteger firstIndex = _buffers->_indexBuffer->_count;
	
	// Value is 0 unless there a page boundary overlap would occur.
	NSUInteger vertexPageOffset = PageOffset(firstVertex, vertexCount);
	if (vertexPageOffset>0) {
		int stop=0; // #1 if we got here then visual bug will be
	}
	
	// Split vertexes into pages of 2^16 vertexes since GLES2 requires indexing with shorts.
	NSUInteger vertexPage = (firstVertex + vertexPageOffset) >> 16;
	NSUInteger vertexPageIndex = (firstVertex + vertexPageOffset) & 0xFFFF;
	
	// Ensure that the buffers have enough storage space.
	NSUInteger indexCount = 3*triangleCount;
	CCVertex *vertexes = CCGraphicsBufferPushElements(_buffers->_vertexBuffer, vertexCount + vertexPageOffset);
	if (vertexPageOffset>0) {
		vertexes = vertexes + vertexPageOffset; // #2 vertices will be stored from beginning of the next page
	}

You can set breakpoint in line with my first comment to easily detect error.

	if (vertexPageOffset>0) {
		int stop=0; // #1 if we got here then visual bug will be
	}

I've added last three lines to fix this issue. I don't know is it solution or just workaround, but it works now.

	if (vertexPageOffset>0) {
		vertexes = vertexes + vertexPageOffset; // #2 vertices will be stored from beginning of the next page
	}

I hope it helps somebody.