#include "block.h" #include "member.h" #include "uniform.h" #define GL_GLEXT_PROTOTYPES #include #include // GL 1.1 functions #include #include #include "fileSystem.h" #include "../array.h" #include "../char.h" #include "sampler2D.h" #include "shader.h" class program{ GLuint samplerIndex = 0; array * uniforms = new array(); array * attributes = new array(); array * blocks = new array(); array * shaders = new array(); GLuint glProgram; addShader( struct shader * shaderInstance ) { this->shaders->add( shaderInstance ); } GLint glGetProgramResourceiv( GLint programProperty, GLint index, GLint Property ) { GLint offsetValues; glGetProgramResourceiv( this->glProgram, programProperty, index, 1, &Property , 1, 0, &offsetValues ); return offsetValues; } GLchar * glGetProgramResourceName( GLint programProperty, GLint index, GLint nameLength ) { GLchar name[ GL_NAME_LENGTH + 1 ]; glGetProgramResourceName( this->glProgram, programProperty, index, GL_NAME_LENGTH + 1, 0, name ); return name; } void extractBlocks() { GLint programInterfaces[2] = { GL_SHADER_STORAGE_BLOCK, GL_UNIFORM_BLOCK }; // GL_UNIFORM_BLOCK GLint programProperties[2] = { GL_BUFFER_VARIABLE, GL_UNIFORM }; // GL_UNIFORM , GL_PROGRAM_INPUT GLenum programBufferTypes[2] = { GL_SHADER_STORAGE_BUFFER, GL_UNIFORM_BUFFER }; for (int blockTypeIndex = 0; blockTypeIndex < 2; ++blockTypeIndex) { GLint program = this->glProgram; GLint numActiveResources; GLint programInterface = programInterfaces[blockTypeIndex]; // GL_UNIFORM_BLOCK GLint programProperty = programProperties[blockTypeIndex]; // GL_UNIFORM GLenum programBufferType = programBufferTypes[blockTypeIndex]; glGetProgramInterfaceiv( program, programInterface, GL_ACTIVE_RESOURCES, &numActiveResources ); //printf("extractShaderStorageBuffers %i\n\n", numActiveResources); for ( GLuint blockIndex = 0; blockIndex < numActiveResources; blockIndex++ ) { struct block * blockInstance = new block(); //GLint blockIndex = this->glGetProgramResourceiv( programInterface, blockIndex, GL_BLOCK_INDEX ); GLint blockNameLength = this->glGetProgramResourceiv( programInterface, blockIndex, GL_NAME_LENGTH ); blockInstance->bufferSize = this->glGetProgramResourceiv( programInterface, blockIndex, GL_BUFFER_DATA_SIZE ); GLint numberActiveVariables = this->glGetProgramResourceiv( programInterface, blockIndex, GL_NUM_ACTIVE_VARIABLES ); blockInstance->bindingPoint = this->glGetProgramResourceiv( programInterface, blockIndex, GL_BUFFER_BINDING ); //const GLchar * name = this->glGetProgramResourceName( programInterface, blockIndex, blockNameLength ); GLchar name[ GL_NAME_LENGTH + 1 ]; glGetProgramResourceName( this->glProgram, programInterface, blockIndex, GL_NAME_LENGTH + 1, NULL, name ); blockInstance->name = malloc( GL_NAME_LENGTH ); strcpy( blockInstance->name, name ); blockInstance->bufferType = programBufferType; printf("block:%s \n\n", blockInstance->name ); printf(" block name %s\n", blockInstance->name); printf(" block buffer size: %i\n", blockInstance->bufferSize); printf(" block binding point: %i\n\n", blockInstance->bindingPoint); GLint indices[ numberActiveVariables ]; GLenum member = GL_ACTIVE_VARIABLES; glGetProgramResourceiv( program, programInterface, blockIndex, 1, &member, numberActiveVariables, 0, indices ); printf(" number of variables: %i\n\n\n", numberActiveVariables); // add block for ( GLuint index = 0; index < numberActiveVariables; index++ ) { struct member * memberInstance = new member(); GLint itemIndex = indices[ index ]; memberInstance->index = itemIndex; GLint nameLength = this->glGetProgramResourceiv( programProperty, itemIndex, GL_NAME_LENGTH ); memberInstance->offset = this->glGetProgramResourceiv( programProperty, itemIndex, GL_OFFSET ); memberInstance->type = this->glGetProgramResourceiv( programProperty, itemIndex, GL_TYPE ); memberInstance->arrayStride = this->glGetProgramResourceiv( programProperty, itemIndex, GL_ARRAY_STRIDE ); memberInstance->size = this->glGetProgramResourceiv( programProperty, itemIndex, GL_ARRAY_SIZE ); int topLevelSize = this->glGetProgramResourceiv( programProperty, itemIndex, GL_TOP_LEVEL_ARRAY_SIZE ); int topLevelStride = this->glGetProgramResourceiv( programProperty, itemIndex, GL_TOP_LEVEL_ARRAY_STRIDE ); if( memberInstance->arrayStride == 0 ) { memberInstance->arrayStride = topLevelStride; } memberInstance->topLevelSize = topLevelSize; // memberInstance->name = this->glGetProgramResourceName( programProperty, itemIndex, nameLength ); GLchar memberName[ GL_NAME_LENGTH + 1 ]; glGetProgramResourceName( this->glProgram, programProperty, itemIndex, GL_NAME_LENGTH + 1, NULL, memberName ); memberInstance->name = malloc( GL_NAME_LENGTH ); strcpy( memberInstance->name, memberName ); printf(" offset: #%i name: %s vec2: %i offset: %i itemSize / arrayStride: %i Array size: %i toplevel size: %i top level size: %i \n\n", memberInstance->index, memberInstance->name, memberInstance->type == GL_FLOAT_VEC2, memberInstance->offset, memberInstance->arrayStride, memberInstance->size, topLevelSize, topLevelStride ); blockInstance->add( memberInstance ); } blockInstance->createBuffer(); this->blocks->add( blockInstance ); } } } struct block * createNewBlock( char * blockName ) { printf("Copy buffer: %s\n\n", blockName); block * originalBlock = this->getBlock( blockName ); block * blockCopy = new block(); blockCopy->members = originalBlock->members; blockCopy->bindingPoint = originalBlock->bindingPoint; blockCopy->index = originalBlock->index; blockCopy->bufferSize = originalBlock->bufferSize; blockCopy->createBuffer(); return blockCopy; } struct block * getBlock( char * blockName ) { int blockCount = this->blocks->length(); for ( int i = 0; i < blockCount; ++i ) { block * currentBlock = this->blocks->get( i ); char * currentBlockName = currentBlock->name; if( currentBlockName == blockName ) { return currentBlock; } } return NULL; } create() { this->glProgram = glCreateProgram(); array * shaders = this->shaders; int shaderCount = shaders->length(); for (int i = 0; i < shaderCount; ++i) { shader * currentShader = shaders->get( i ); glAttachShader( this->glProgram, currentShader->glShader ); } glLinkProgram( this->glProgram ); glUseProgram( this->glProgram ); this->extractBlocks(); this->extractAttributes(); this->extractUniforms(); } bindBlock( char * blockName ) { block * currentBlock = this->getBlock( blockName ); glBindBufferBase( currentBlock->bufferType, currentBlock->bindingPoint, currentBlock->buffer ); } use() { glUseProgram( this->glProgram ); } extractUniforms() { int attributeCount = 0; GLsizei bufSize = 64; GLsizei length; // name length GLint size; GLenum type; // type of the variable (float, vec3 or mat4, etc) int uniformCount = 0; glGetProgramiv( this->glProgram, GL_ACTIVE_UNIFORMS, &uniformCount ); for (int i = 0; i < uniformCount; i++) { struct uniform * uniformInstance = new uniform(); GLenum type; GLchar name[bufSize]; glGetActiveUniform( this->glProgram, ( GLuint ) i, bufSize, &length, &size, &type, uniformInstance->name ); //printf( " Uniform #%d Type: %u Name: %s\n", i, type, uniformInstance->name ); GLint uniformLocation = glGetUniformLocation( this->glProgram, uniformInstance->name ); uniformInstance->location = uniformLocation; uniformInstance->type = type; this->uniforms->add( uniformInstance ); } } extractAttributes() { int attributeCount = 0; GLsizei bufSize = 64; GLsizei length; // name length GLint size; GLenum type; // type of the variable (float, vec3 or mat4, etc) glGetProgramiv( this->glProgram, GL_ACTIVE_ATTRIBUTES, &attributeCount ); for (int i = 0; i < attributeCount; i++) { GLenum type; attribute * attributeInstance = new attribute(); glGetActiveAttrib( this->glProgram, ( GLuint ) i, bufSize, &length, &size, &type, attributeInstance->name); //printf(" Attribute #%d Type: %u Name: %s size: %i\n", i, type, attributeInstance->name, size); GLint attributeLocation = glGetAttribLocation( this->glProgram, attributeInstance->name ); glEnableVertexAttribArray( attributeLocation ); attributeInstance->location = attributeLocation; //attributeInstance.name = name; attributeInstance->type = type; this->attributes->add( attributeInstance ); } } struct attribute * getAttributeByName( char * attributeName ) { int attributeCount = this->attributes->length(); //printf("uniformCount: %i\n\n", attributeCount); for ( int i = 0; i < attributeCount; ++i ) { struct attribute * currentAttribute = this->attributes->get( i ); char * currentAttributeName = currentAttribute->name; //printf("attributeName->name: %s %s\n\n", currentAttributeName, attributeName ); if( currentAttributeName == attributeName ) { return currentAttribute; } } return NULL; } void setUniform( char * name, void * value ) { int uniformCount = this->uniforms->length(); // printf("uniformCount: %i\n\n", uniformCount); for (int i = 0; i < uniformCount; ++i) { uniform * currentUniform = this->uniforms->get( i ); char * uniformName = (char *)currentUniform->name; // printf("currentUniform->name: %s\n\n", uniformName); if( uniformName == name ) { //printf("\n\n Update this uniform %s\n\n", name); switch( currentUniform->type ) { case GL_FLOAT_VEC2: vector2 * vector2Value = ( vector2 * ) value; //printf("\n\n this is an float vec2 %f %f \n\n", vector2Value->x, vector2Value->y ); glUniform2f( currentUniform->location, vector2Value->x, vector2Value->y ); break; case GL_FLOAT_VEC3: vector3 * vector3Value = ( vector3 * ) value; //printf("\n\n this is an float vec3 %f %f %f \n\n", vector3Value->x, vector3Value->y, vector3Value->z); glUniform3f( currentUniform->location, vector3Value->x, vector3Value->y, vector3Value->z ); break; case GL_SAMPLER_2D: this->updateSampler2D( currentUniform, value ); break; case GL_SAMPLER_2D_ARRAY: this->updateSampler2D( currentUniform, value ); break; } } } } updateSampler2D( uniform * currentUniform, void * value ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); sampler2D * sampler = ( sampler2D * ) value; if( !sampler->binded ) { sampler->index = this->samplerIndex++; sampler->bind(); //printf("sampler->index: %i \n", sampler->index); } glActiveTexture( GL_TEXTURE0 + sampler->index ); glBindTexture( sampler->target, sampler->glTexture ); //glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,GL_UNSIGNED_BYTE, texture ); glUniform1i( currentUniform->location, sampler->index ); } }