Files
2025-11-17 10:28:09 +01:00

535 lines
11 KiB
C

#include "block.h"
#include "member.h"
#include "uniform.h"
#define GL_GLEXT_PROTOTYPES
#include <GL/glext.h>
#include <GL/gl.h> // GL 1.1 functions
#include <GL/glx.h>
#include <stdio.h>
#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 );
}
}