Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 3 123 LastLast
Results 1 to 10 of 30

Thread: SSBO and VBO help

  1. #1

    SSBO and VBO help

    Hello,

    I decided to implement Batch Rendering using SSBO, where SSBO will contain an array of structs that contains all data for each object (lets say 100 objects). Along the way I also had to change the VBO in order to accommodate some changes from the previous pipeline.

    The problem is, nothing renders. I doubled checked my math and everything checks out. glGetError() also showed no issues (perhaps I didn't check for the proper enumerator), so I figured to ask for the forum's opinion.


    The setup is very simple:
    - each struct has a bunch of flags and other data for each object.
    - as the vertex data is pushed into VBO, the object's index in the array is also pushed into the VBO.
    - shader accesses the struct using the object index that was acquired from vertex data
    - shader uses the struct's data


    This is the struct I am pushing into the SSBO:

    Code :
    struct objectVarsData {
    	float	posVec[3];						// 12	12
    	float	rotVec[3];						// 12	24
    	float	scaleVec;						// 4	28
     
    	int		textureLayer;					// 4	32
     
    	int		drawEnable;						// 4	36
    	int			colorMapEnable;				// 4	40
    	float			colorVec[3];			// 12	52
    	float			alphaScale;				// 4	56
     
    	int			normalMapEnable;			// 4	60
     
    	int			specularMapEnable;			// 4	64
     
    	int			lightMapEnable;				// 4	68
    	float			lightVec[3];			// 12	80
    	float			lightScale;				// 4	84
     
    	int			controlEnable;				// 4	88
    	float			controlColorVec[3];		// 12	100
    };

    This is how initialize my SSBO and VBO:

    Code :
    	// Object VBO
    		glGenBuffers(1, &(this->objectVBO));
    		glBindBuffer(GL_ARRAY_BUFFER, this->objectVBO);
    		glBufferData(GL_ARRAY_BUFFER, graphics2DMaximumVBOSize_Byte, NULL, GL_STATIC_DRAW);
     
    		glGenVertexArrays(1, &(this->objectVAO));
    		glBindVertexArray(this->objectVAO);
    		glBindBuffer(GL_ARRAY_BUFFER, this->objectVAO);
    		glVertexAttribPointer(0, graphicsVertexPosSize,		  GL_FLOAT, GL_FALSE, graphicsVertexDataSize_Byte, NULL);
    		glEnableVertexAttribArray(0);
    		glVertexAttribPointer(1, graphicsVertexTangentSize,	  GL_FLOAT, GL_FALSE, graphicsVertexDataSize_Byte,	(GLvoid*)(sizeof(GLfloat) * graphicsVertexTangentOffset));
    		glEnableVertexAttribArray(1);
    		glVertexAttribPointer(2, graphicsVertexBitangentSize, GL_FLOAT, GL_FALSE, graphicsVertexDataSize_Byte,	(GLvoid*)(sizeof(GLfloat) * graphicsVertexBitangentOffset));
    		glEnableVertexAttribArray(2);
    		glVertexAttribPointer(3, graphicsVertexNormalSize,	  GL_FLOAT, GL_FALSE, graphicsVertexDataSize_Byte,	(GLvoid*)(sizeof(GLfloat) * graphicsVertexNormalOffset));
    		glEnableVertexAttribArray(3);
    		glVertexAttribPointer(4, graphicsVertexUVSize,		  GL_FLOAT, GL_FALSE, graphicsVertexDataSize_Byte,	(GLvoid*)(sizeof(GLfloat) * graphicsVertexUVOffset));
    		glEnableVertexAttribArray(4);
    		glVertexAttribIPointer(5, graphicsVertexObjectIndexSize, GL_UNSIGNED_INT, graphicsVertexDataSize_Byte,	(GLvoid*)(sizeof(GLfloat) * graphicsVertexObjectIndexOffset));
    		glEnableVertexAttribArray(5);
     
     
    	// Object SSBO
    		glGenBuffers(1, &(this->objectSSBO));
    		glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->objectSSBO);
    		glBufferData(GL_SHADER_STORAGE_BUFFER, graphics2DMaximumSSBOSize_Byte, NULL, GL_STATIC_DRAW);
    		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this->objectSSBO);


    Then I push everything into the substack (currently I don't account for substack overflow for testing I just do 1 object):

    Code :
    		unsigned int objectCount = 0;
    		unsigned int vertexIndex = 0;
    		graphicsObject * bufferObject;
     
    		std::cout << "         - Pushing Objects:" << std::endl;
    		for (unsigned int i = 0; i < this->objectQueue->size; i++) {
    			bufferObject = (graphicsObject *) this->objectQueue->lowestEntry->attachedObject;
     
    			std::cout << "            Object " << bufferObject->objectID << " with " << bufferObject->meshSize << " geometries at " << graphics2DStartDepth + graphics2DDepthChange*(objectCount) << std::endl;
    			this->push2DObject( bufferObject, &objectCount, &vertexIndex);
     
    			graphicsLinkedListRotateBackward(this->objectQueue);
     
    			if (objectCount == graphics2DMaximumObjects) { // Assumes 1 object per push
    				std::cout << "         - Flushing Substack (Substack full)..."  << std::endl;
    				std::cout << "            Object Count: " << objectCount << std::endl;
    				std::cout << "            Vertex Count: " << vertexIndex << std::endl;
     
    				this->drawSubStack(vertexIndex);	// Stages 1,2 and 3
    				this->drawToBuffer();				// Stage 4
     
    				std::cout << "            - Continuing Pushing..." << std::endl;
    				objectCount = 0;
    				vertexIndex = 0;
    			}
     
    		}
     
    		if (vertexIndex > 0) {
    			std::cout << "         - Flushing Substack (Remains):" << std::endl;
    			std::cout << "            Object Count: " << objectCount << std::endl;
    			std::cout << "            Vertex Count: " << vertexIndex << std::endl;
     
    			this->drawSubStack(vertexIndex);	// Stages 1,2 and 3
    			this->drawToBuffer();				// Stage 4
    		}

    Where each object pushed using:

    Code :
    	unsigned int objectIndex = *objectCount;
    	objectCount[0]++;
     
    	// Load the data into buffer struct
    		this->objectDataBuffer.posVec[0] = object->posVec[0];
    		this->objectDataBuffer.posVec[1] = object->posVec[1];
    		this->objectDataBuffer.posVec[2] = 1.0 - graphics2DDepthChange*(*objectCount); // change if the triangles are outside the camera limit
    		this->objectDataBuffer.rotVec[0] = object->rotVec[0];
    		this->objectDataBuffer.rotVec[1] = object->rotVec[1];
    		this->objectDataBuffer.rotVec[2] = object->rotVec[2];
    		this->objectDataBuffer.scaleVec = *(object->scaleVec);
     
    		this->objectDataBuffer.textureLayer = object->textureLayer;
     
    		this->objectDataBuffer.drawEnable = object->drawEnable;
    			this->objectDataBuffer.colorMapEnable = object->colorMapEnable;
    				this->objectDataBuffer.colorVec[0] = object->colorVec[0];
    				this->objectDataBuffer.colorVec[1] = object->colorVec[1];
    				this->objectDataBuffer.colorVec[2] = object->colorVec[2];
    				this->objectDataBuffer.alphaScale = *(object->alphaScale);
     
    			this->objectDataBuffer.normalMapEnable = object->normalMapEnable;
     
    			this->objectDataBuffer.specularMapEnable = object->specularMapEnable;
     
    			this->objectDataBuffer.lightMapEnable = object->lightMapEnable;
    				this->objectDataBuffer.lightVec[0] = object->lightVec[0];
    				this->objectDataBuffer.lightVec[1] = object->lightVec[1];
    				this->objectDataBuffer.lightVec[2] = object->lightVec[2];
    				this->objectDataBuffer.lightScale = *(object->lightScale);
     
    			this->objectDataBuffer.controlEnable = object->controlEnable;
    				this->objectDataBuffer.controlColorVec[0] = object->controlColorVec[0];
    				this->objectDataBuffer.controlColorVec[1] = object->controlColorVec[1];
    				this->objectDataBuffer.controlColorVec[2] = object->controlColorVec[2];
     
    	// Load the data into OpenGL buffers
    	//		Shader Storage Data
    		glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->objectSSBO);
    		glBufferSubData(GL_SHADER_STORAGE_BUFFER, sizeof(objectVarsData)*objectIndex, sizeof(objectVarsData), &(this->objectDataBuffer));
     
    	//		Vertex Array Data
    	glBindBuffer(GL_ARRAY_BUFFER, this->objectVBO);
    	for (int i = 0; i < object->meshSize; i++) {
    			glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex),																 graphicsVertexMeshDataSize_Byte,	 &object->meshPoints[(*vertexIndex) * graphicsVertexMeshDataSize]);
    			glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex) + graphicsVertexMeshDataSize_Byte,							 graphicsVertexUVSize_Byte,			 &object->uvPoints[(*vertexIndex) * graphicsVertexUVSize]);
    			glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex) + graphicsVertexMeshDataSize_Byte + graphicsVertexUVSize_Byte, graphicsVertexObjectIndexSize_Byte,	&objectIndex);
     
    			vertexIndex[0]++;
     
    			glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex),																 graphicsVertexMeshDataSize_Byte,	 &object->meshPoints[(*vertexIndex) * graphicsVertexMeshDataSize]);
    			glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex) + graphicsVertexMeshDataSize_Byte,							 graphicsVertexUVSize_Byte,			 &object->uvPoints[(*vertexIndex) * graphicsVertexUVSize]);
    			glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex) + graphicsVertexMeshDataSize_Byte + graphicsVertexUVSize_Byte, graphicsVertexObjectIndexSize_Byte, &objectIndex);
     
    			vertexIndex[0]++;
     
    			glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex),																 graphicsVertexMeshDataSize_Byte,	 &object->meshPoints[(*vertexIndex) * graphicsVertexMeshDataSize]);
    			glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex) + graphicsVertexMeshDataSize_Byte,							 graphicsVertexUVSize_Byte,			 &object->uvPoints[(*vertexIndex) * graphicsVertexUVSize]);
    			glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex) + graphicsVertexMeshDataSize_Byte + graphicsVertexUVSize_Byte, graphicsVertexObjectIndexSize_Byte, &objectIndex);
     
    			vertexIndex[0]++;
     
    			if ((*vertexIndex / 3) >= graphics2DMaximumTriangles) {
    				std::cout << "   Object Count: " << objectCount << std::endl;
    				std::cout << "      Vertex Count: " << vertexIndex << std::endl;
     
    				this->drawSubStack((*vertexIndex));	// Stages 1,2 and 3
    				this->drawToBuffer();				// Stage 4
     
    				(*objectCount) = 0;
    				(*vertexIndex) = 0;
    			}
    	}

    Finally, I draw the objects:

    Code :
    		glBindFramebuffer(GL_FRAMEBUFFER, this->subSceneFBO1);
    		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    		glUseProgram(this->subSceneShaderArray[0]);
     
    			glActiveTexture(GL_TEXTURE0);
    			glBindTexture(GL_TEXTURE_2D, this->textureAsset->colorMapID);
    			glUniform1i(this->stage1ColorMapLocation, 0);
     
    			glActiveTexture(GL_TEXTURE1);
    			glBindTexture(GL_TEXTURE_2D, this->textureAsset->normalMapID);
    			glUniform1i(this->stage1NormalMapLocation, 1);
     
    			glActiveTexture(GL_TEXTURE2);
    			glBindTexture(GL_TEXTURE_2D, this->textureAsset->specularMapID);
    			glUniform1i(this->stage1SpecularMapLocation, 2);
     
    			glActiveTexture(GL_TEXTURE3);
    			glBindTexture(GL_TEXTURE_2D, this->textureAsset->lightMapID);
    			glUniform1i(this->stage1LightMapLocation, 3);
     
    		glEnable(GL_DEPTH_TEST);
    		glDepthMask(GL_TRUE);
    		glDisable(GL_BLEND);
     
    			// Binding SSBO
    			glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->objectSSBO);
    			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this->objectSSBO);
     
    			// Binding VBO
    			glBindVertexArray(this->objectVAO);
    			glBindBuffer(GL_ARRAY_BUFFER, this->objectVBO);
    			glDrawArrays(GL_TRIANGLES, 0, vertexIndex*graphicsVertexDataSize);

    Vertex shader:

    Code :
    // shadertype=glsl
    #version 450
     
    layout (location = 0) in vec3	vertexPos;
    layout (location = 1) in vec3	tangent;
    layout (location = 2) in vec3	bitangent;
    layout (location = 3) in vec3	normal;
    layout (location = 4) in vec2	texCoord;
    layout (location = 5) in uint	objectIndex; 
     
    layout(std140, binding = 0) uniform cameraVars
    {
    		mat4	projectionMat;	// 64 bytes
    		mat4	cameraMat;		// 128 bytes
    };
     
    struct objectVarsData {
    			vec3	posVec;
    			vec3	rotVec;
    			vec3	scaleVec;
     
    			int		textureLayer;
     
    			int		drawEnable;
    			int			colorMapEnable;
    			vec3			colorVec;
    			float			alphaScale;
     
    			int			normalMapEnable;
     
    			int			specularMapEnable;
     
    			int			lightMapEnable;
    			vec3			lightVec;
    			float			lightScale;
     
    			int			controlEnable;
    	highp	vec3			controlColorVec;
    };
     
    layout(std430, binding = 1) buffer objectVars
    {
    	objectVarsData objectVarsArray[10000];
    };
     
    out vec2 tex_coord;
    out mat3 normal_tran_mat;
    out float object_depth;
    flat out uint object_index;
     
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////
    void main() {
    	object_index = objectIndex;
     
    	objectVarsData objectVarsDataBuffer = objectVarsArray[object_index];
     
    	vec3 objectPosVec = objectVarsDataBuffer.posVec;
    	vec3 objectRotVec = objectVarsDataBuffer.rotVec;
    	vec3 objectScaleVec = objectVarsDataBuffer.scaleVec;
     
    	vec3 vertexTangent = tangent;
    	vec3 vertexBitangent = bitangent;
    	vec3 vertexNormal = normal;
     
    	// WORLD SPACE MATRIX CREATION
    		// Position
    		mat4	objectPosMat = mat4(1.0);
    				objectPosMat[3].xyz = vec3(objectPosVec.x, -objectPosVec.y, objectPosVec.z);
     
    		// Rotation X
    		mat4	objectRotXMat = mat4(1.0);
    				objectRotXMat[1] = vec4(0.0,  cos(objectRotVec[0]), sin(objectRotVec[0]), 0.0);
    				objectRotXMat[2] = vec4(0.0, -sin(objectRotVec[0]), cos(objectRotVec[0]), 0.0);
     
    		// Rotation Y
    		mat4	objectRotYMat = mat4(1.0);
    				objectRotYMat[0] = vec4(cos(objectRotVec[1]), 0.0, -sin(objectRotVec[1]), 0.0);
    				objectRotYMat[2] = vec4(sin(objectRotVec[1]), 0.0, cos(objectRotVec[1]), 0.0);
     
    		// Rotation Z
    		mat4	objectRotZMat = mat4(1.0);
    				objectRotZMat[0] = vec4( cos(objectRotVec[2]), sin(objectRotVec[2]), 0.0, 0.0);
    				objectRotZMat[1] = vec4(-sin(objectRotVec[2]), cos(objectRotVec[2]), 0.0, 0.0);
     
    	// TOTAL TRANSFORMATION MATRIX
    		mat4 transformMat = cameraMat*objectPosMat*objectRotZMat*objectRotYMat*objectRotXMat; //cameraMat
     
    	// TRANSFORMING OBJECT
    		tex_coord = texCoord;
     
    		object_depth = 1.0 - objectPosVec[2];
     
    		vec4 bufferVec1 = normalize(transformMat*vec4(normalize(vertexTangent), 0.0));
    		vec4 bufferVec2 = normalize(transformMat*vec4(normalize(vertexBitangent), 0.0));
    		vec4 bufferVec3 = normalize(transformMat*vec4(normalize(vertexNormal), 0.0));
    		normal_tran_mat = mat3(bufferVec1.xyz, bufferVec2.xyz, bufferVec3.xyz); 
     
    		vec3 vertexPosBuffer = vertexPos;
    		vertexPosBuffer.x = vertexPos.x*objectScaleVec.x;
    		vertexPosBuffer.y = vertexPos.y*objectScaleVec.y;
    		vertexPosBuffer.z = vertexPos.z*objectScaleVec.z;
     
    		gl_Position = projectionMat*transformMat*vec4(vertexPosBuffer, 1.0); //projectionMat
    }

    Fragment shader:

    Code :
    // shadertype=glsl
    #version 450
     
    uniform	sampler2D colorMap;
    uniform sampler2D normalMap;
    uniform sampler2D specularMap;
    uniform sampler2D lightMap;
     
    struct objectVarsData {
    			vec3	posVec;
    			vec3	rotVec;
    			vec3	scaleVec;
     
    			int		textureLayer;
     
    			int		drawEnable;
    			int			colorMapEnable;
    			vec3			colorVec;
    			float			alphaScale;
     
    			int			normalMapEnable;
     
    			int			specularMapEnable;
     
    			int			lightMapEnable;
    			vec3			lightVec;
    			float			lightScale;
     
    			int			controlEnable;
    	highp	vec3			controlColorVec;
    };
     
    layout(std430, binding = 1) buffer objectVars
    {
    	objectVarsData objectVarsArray[10000];
    };
     
    in vec2 tex_coord;
    in mat3 normal_tran_mat;
    in float object_depth;
    flat in uint object_index;
     
    layout(location = 0) out vec4 stage1ColorMap;
    layout(location = 1) out vec4 stage1NormalMap;
    layout(location = 2) out vec4 stage1SpecularMap;
    layout(location = 3) out vec4 stage1LightMap;
    layout(location = 4) out vec4 stage1ControlMap;
     
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////
    void main() {
     
    	objectVarsData objectVarsDataBuffer = objectVarsArray[object_index];
     
    		int		textureLayer =	objectVarsDataBuffer.textureLayer;
    		int		drawEnable = objectVarsDataBuffer.drawEnable;
    		int			colorMapEnable = objectVarsDataBuffer.colorMapEnable;
    		vec3			colorVec = objectVarsDataBuffer.colorVec;
    		float			alphaScale = clamp(objectVarsDataBuffer.alphaScale, 0.0, 1.0);
    		int			normalMapEnable = objectVarsDataBuffer.normalMapEnable;
    		int			specularMapEnable = objectVarsDataBuffer.specularMapEnable;
    		int			lightMapEnable = objectVarsDataBuffer.lightMapEnable;
    		vec3			lightColorVec = objectVarsDataBuffer.lightVec;
    		float			lightScale = objectVarsDataBuffer.lightScale;
    		int			controlEnable = objectVarsDataBuffer.controlEnable;
    	highp vec3			controlColorVec = objectVarsDataBuffer.controlColorVec;
     
    	vec4 textureBuffer = texture(colorMap, tex_coord);
    	vec4 normalBuffer = texture(normalMap, tex_coord);
    	vec4 specularBuffer = texture(specularMap, tex_coord);
    	vec4 lightBuffer = texture(lightMap, tex_coord);
     
    	float fragmentAlpha = alphaScale*textureBuffer.a;
    	fragmentAlpha = clamp(fragmentAlpha, 0.0, 1.0);
     
    	if (fragmentAlpha == 1.0) {
     
    		// CONTROL MAP          controlColorVec
    			if (controlEnable == 1) {
    					stage1ControlMap = vec4(controlColorVec, 1.0);
    			} else {
    					stage1ControlMap = vec4(0.0, 0.0, 0.0, 0.0);
    			}
     
    		// IMAGE MAPS
    			if (drawEnable == 1) {
     
    				if (colorMapEnable == 0) {
    					stage1ColorMap = vec4(colorVec, 1.0);
    				} else {
    					stage1ColorMap = vec4(textureBuffer.xyz, 1.0);
    				}
     
    				if (normalMapEnable == 0) {
    					stage1NormalMap =  vec4(0.0, 0.0, 0.0, 1.0);
    				} else {
    					vec3 normalFromMap = 2.0*normalBuffer.xyz - vec3(1.0, 1.0, 1.0);
    					stage1NormalMap = vec4((normalize(normal_tran_mat*normalFromMap) + 1.0) / 2.0, 1.0);
    				}
     
    				if (specularMapEnable == 0) {
    					stage1SpecularMap = vec4(0.0, 0.0, 0.0, 1.0);
    				} else {
    					stage1SpecularMap =  vec4(vec3(specularBuffer.x),1.0);
    				}
     
    				if (lightMapEnable == 0) {
    					stage1LightMap = vec4(0.0, 0.0, 0.0, 1.0);
    				} else {
    					stage1LightMap = vec4(lightBuffer.xyz,1.0);
    				}
    			} else {
    				stage1ColorMap = vec4(0.0, 0.0, 0.0, 0.0);	
    				stage1NormalMap = vec4(0.0, 0.0, 0.0, 0.0);	
    				stage1SpecularMap = vec4(0.0, 0.0, 0.0, 0.0);	
    				stage1LightMap = vec4(0.0, 0.0, 0.0, 0.0);	
    			}
     
    			gl_FragDepth = object_depth;
    	} else {
    		discard;
    	}
    }

    These are the only parts of the code that were changed, the rest of my code was unchanged from previous render version and well tested.

    Any suggestions on debugging techniques for SSBOs would be awesome.

    Thanks

  2. #2
    It appears I made a mistake in the code above, this is how I upload the data to the VBO:


    Code cpp:
        unsigned int objectIndex = *objectCount;
        objectCount[0]++;
     
        // Load the data into buffer struct
            this->objectDataBuffer.posVec[0] = object->posVec[0];
            this->objectDataBuffer.posVec[1] = object->posVec[1];
            this->objectDataBuffer.posVec[2] = 1.0 - graphics2DDepthChange*(*objectCount); // change if the triangles are outside the camera limit
            this->objectDataBuffer.rotVec[0] = object->rotVec[0];
            this->objectDataBuffer.rotVec[1] = object->rotVec[1];
            this->objectDataBuffer.rotVec[2] = object->rotVec[2];
            this->objectDataBuffer.scaleVec = *(object->scaleVec);
     
            this->objectDataBuffer.textureLayer = object->textureLayer;
     
            this->objectDataBuffer.drawEnable = object->drawEnable;
                this->objectDataBuffer.colorMapEnable = object->colorMapEnable;
                    this->objectDataBuffer.colorVec[0] = object->colorVec[0];
                    this->objectDataBuffer.colorVec[1] = object->colorVec[1];
                    this->objectDataBuffer.colorVec[2] = object->colorVec[2];
                    this->objectDataBuffer.alphaScale = *(object->alphaScale);
     
                this->objectDataBuffer.normalMapEnable = object->normalMapEnable;
     
                this->objectDataBuffer.specularMapEnable = object->specularMapEnable;
     
                this->objectDataBuffer.lightMapEnable = object->lightMapEnable;
                    this->objectDataBuffer.lightVec[0] = object->lightVec[0];
                    this->objectDataBuffer.lightVec[1] = object->lightVec[1];
                    this->objectDataBuffer.lightVec[2] = object->lightVec[2];
                    this->objectDataBuffer.lightScale = *(object->lightScale);
     
                this->objectDataBuffer.controlEnable = object->controlEnable;
                    this->objectDataBuffer.controlColorVec[0] = object->controlColorVec[0];
                    this->objectDataBuffer.controlColorVec[1] = object->controlColorVec[1];
                    this->objectDataBuffer.controlColorVec[2] = object->controlColorVec[2];
     
        // Load the data into OpenGL buffers
        //        Shader Storage Data
            glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->objectSSBO);
            glBufferSubData(GL_SHADER_STORAGE_BUFFER, sizeof(objectVarsData)*objectIndex, sizeof(objectVarsData), &(this->objectDataBuffer));
     
        //        Vertex Array Data
        glBindVertexArray(this->subSceneVAO);
        glBindBuffer(GL_ARRAY_BUFFER, this->objectVBO);
        for (int i = 0; i < (object->meshSize)*3; i++) {
                // Vertex Data
                glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex) + graphicsVertexPosOffset_Byte            , graphicsVertexMeshDataSize_Byte        , (const GLvoid *) &(object->meshPoints[(*vertexIndex) * graphicsVertexMeshDataSize]));
     
                // UV Vector
                glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex) + graphicsVertexUVOffset_Byte                , graphicsVertexUVSize_Byte                , (const GLvoid *) &(object->uvPoints[(*vertexIndex) * graphicsVertexUVSize]));
     
                // Object ID
                glBufferSubData(GL_ARRAY_BUFFER, graphicsVertexDataSize_Byte * (*vertexIndex) + graphicsVertexObjectIndexOffset_Byte    , graphicsVertexObjectIndexSize_Byte    , (const GLvoid *) objectCount);
     
                vertexIndex[0]++;
        }


    Each vertex is supposed to have:
    -vertex data (vec3)
    -tangent data (vec3)
    -bitangent data (vec3)
    -normal data (vec3)
    -UV data (vec2)
    -Object Index (uint) - the last one will be used to access the data of the object that the specific drawn triangle belongs to (object data is kept in SSBO)

    I did some debugging, starting by disabling SSBO and a whole bunch of shader things. It appears the culprit is my VBO. Instead of 2 test triangles being rendered, I get a mishapen single one. That disappears after the 2nd frame is drawn (then I get empty screen).

    At this point, I was wondering whether the uint in the vertex data (that's otherwise full of floats) can be the issue.

    Also, this is kinda hard to debug. I was wondering whether it is a good practice (not just from debugging point of view) to create an application buffer, that keeps all the data before uploading the entire thing to opengl? So having a single glBufferData for the enture buffer, instead of multiple glBufferSubDatas. Will it make any difference?
    Last edited by Dark Photon; 01-29-2018 at 04:44 AM.

  3. #3
    Member Regular Contributor
    Join Date
    May 2016
    Posts
    466
    Quote Originally Posted by CaptainSnugglebottom View Post
    I was wondering whether it is a good practice (not just from debugging point of view) to create an application buffer, that keeps all the data before uploading the entire thing to opengl? So having a single glBufferData for the enture buffer, instead of multiple glBufferSubDatas. Will it make any difference?
    yes, it will. read about buffer streaming, check out the commands:
    --> gl{Named}BufferData() with the same size AND usage hint
    --> glMap{Named}BufferRange() and the possible mapping flags

    https://www.khronos.org/opengl/wiki/...ject_Streaming
    https://www.khronos.org/registry/Ope...fferData.xhtml
    https://www.khronos.org/registry/Ope...ferRange.xhtml

  4. #4
    Thanks.

    But does that mean that using my current way (huge VBO + lots of glBufferSubData commands) is incorrect and will never work?

    PS.

    If I use different Vertex Array structures between different rendering stages, do I need to call glEnableVertexAttribArray and specifically glDisableVertexAttribArray between each stage?

    What would happen if after stage 1 that uses 5 vertex attributes, I call stage 2 uses only 2 (with different shader of course). How would OpenGL treat unused 3 attributes?
    Last edited by CaptainSnugglebottom; 01-30-2018 at 08:28 AM.

  5. #5
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,789
    Quote Originally Posted by CaptainSnugglebottom View Post
    But does that mean that using my current way (huge VBO + lots of glBufferSubData commands) is incorrect and will never work?
    It should work but it's very unlikely to ever be efficient.

    Graphics are like networking and hard disks - they can be very latency-sensitive, so lots of small updates will always compare unfavourably to very few large updates.

  6. #6
    Member Regular Contributor
    Join Date
    May 2016
    Posts
    466
    Quote Originally Posted by CaptainSnugglebottom View Post
    If I use different Vertex Array structures between different rendering stages, do I need to call glEnableVertexAttribArray and specifically glDisableVertexAttribArray between each stage?
    thats what VAOs are about: storing the vertex attributes, their format / source buffer etc, if by "Vertex Array structures" you mean VAOs then: no, its sufficient to set up the VAOs once and just bind then when needed

  7. #7
    Thank you very much for your help. I will try changing my code to use 1 big VBO update.


    Still wondering what I'm doing wrong tho. After I commented out most of my code, it just draws 1 single triangle that is not defined by any values I'm passing. Hope it doesn't come back to haunt my new implementation.

  8. #8
    Hello again.

    I finally had a chance to replace my glBufferSubData with the glMapBuffer function, at least for the VBO, and that seems to be working well enough. However, the SSBO (that still uses glBufferSubData) is still having issues.

    Test setup: 2 objects, different geometries, different position and rotation vectors.

    Output:
    - Different geometries (VBO finally working).
    - SSBO for some reason only records the first object position vec3 value.
    - The last object will always be rotated by some value. The rotation vector gets ignored except for 1 value (not sure which because of the constant rotation offset).
    - I hardcoded the object index into the buffer to use either first or 2nd object's position, and as expected both objects only do stuff when using the 2nd object's positions. So I don't think VBO is the issue at all.
    - I checked my C++ code, and the pointers in the glBufferSubData are proper. Each object's data is offset by 108 bytes, which corresponds to the struct (the rest of the SSBO related code is unchanged from above):

    Code :
    struct objectVarsData {
    	float	posVec[3];						// 12	12
    	float	rotVec[3];							// 12	24
    	float	scaleVec[3];						// 12	36
     
    	int		textureLayer;					// 4	40
     
    	int		drawEnable;					// 4	44
    	int			colorMapEnable;			// 4	48
    	float			colorVec[3];				// 12	60
    	float			alphaScale;				// 4	64
     
    	int			normalMapEnable;			// 4	68
     
    	int			specularMapEnable;			// 4	72
     
    	int			lightMapEnable;				// 4	76
    	float			lightVec[3];				// 12	88
    	float			lightScale;					// 4	92
     
    	int			controlEnable;				// 4	96
    	float			controlColorVec[3];			// 12	108
    };

    and in the shader:

    Code :
    struct objectVarsData {
    			vec3	posVec;
    			vec3	rotVec;
    			vec3	scaleVec;
     
    			int		textureLayer;
     
    			int		drawEnable;
    			int			colorMapEnable;
    			vec3			colorVec;
    			float			alphaScale;
     
    			int			normalMapEnable;
     
    			int			specularMapEnable;
     
    			int			lightMapEnable;
    			vec3			lightVec;
    			float			lightScale;
     
    			int			controlEnable;
    	highp	vec3			controlColorVec;
    };
     
    layout(std430, binding = 1) buffer objectVars
    {
    	objectVarsData objectVarsArray[100];
    };

    What could cause this bizzare behavior? Some sources state that I should be using vec4 instead of vec3, but the fail to mention cases where std430 is used, which should take care of things. Could this be the issue?

    Most importantly, since glMapBuffer is so much easier to use. I was wondering whether I can use glMapBuffer at the same time, for both VBO and SSBO. So it would look something like that:

    Code :
     
    glMapBuffer(GL_ARRAY_BUFFER, VBO)
    glMapBuffer(GL_SHADER_STORAGE_BUFFER, SSBO)
     
    for (each object) {
       pushDataIntoSSBO()
       pushGeometriesIntoVBO()
    }
     
    grawStuff()
     
    glUnmapBuffer(GL_ARRAY_BUFFER)
    glUnmapBuffer(GL_SHADER_STORAGE_BUFFER)

    Or will this cause an issue?
    Last edited by CaptainSnugglebottom; 02-13-2018 at 06:20 PM.

  9. #9
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,829
    Quote Originally Posted by CaptainSnugglebottom View Post
    What could cause this bizzare behavior? Some sources state that I should be using vec4 instead of vec3, but the fail to mention cases where std430 is used, which should take care of things. Could this be the issue?
    Yes. A vec3 is aligned as if it were a vec4 for both std140 and std430. The only difference between the two is that std140 rounds the alignment of all arrays and structures to that of a vec4, while std430 doesn't.

    See 7.6.2.2 "Standard Uniform Block Layout" in the specification for the precise rules.

  10. #10
    Intern Contributor
    Join Date
    Nov 2017
    Posts
    79
    Quote Originally Posted by CaptainSnugglebottom View Post
    ...Some sources state that I should be using vec4 instead of vec3...
    I had the same problem some time ago.
    I'd recommend you read carefully 7.6.2.2 of https://www.khronos.org/registry/Ope...pec45.core.pdf .

    Those complicated rules made me develop typed buffer, that can bind customized structures to GPU.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •