void COpenGLShaderProgram::GetShaderUniform() { //glGetProgramInterface л┬ий╩й GLint uniformsNum = 0; GLDebug(glGetProgramiv(m_hProgram, GL_ACTIVE_UNIFORMS, &uniformsNum)); if (uniformsNum > 0) { GLint maxLength; GLDebug(glGetProgramiv(m_hProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength)); char *name = new char[maxLength]; for (int i = 0; i < uniformsNum; ++i) { Uniform uniform; GLenum type; GLsizei nameLength; GLDebug(glGetActiveUniform(m_hProgram, i, maxLength, &nameLength, &uniform.m_count, &type, name)); uniform.m_format = GetUniformFormat(type); if (uniform.m_format == UF_UNKNOWN) { printf("GetUniformFormat:UF_UNKNOWN [%s:%d]", __FILE__, __LINE__); } strncpy(uniform.m_name, name, MAX_FILE_NAME - 1); uniform.m_size = GetUniformTypeSize(uniform.m_format); uniform.m_location = i; m_uniforms[i] = uniform; } delete name; } }
void Shader::RecompileInternal(BaseObject * caller, void * param, void *callerData) { DVASSERT((vertexShader == 0) && (fragmentShader == 0) && (program == 0)); if (!CompileShader(&vertexShader, GL_VERTEX_SHADER, vertexShaderData->GetSize(), (GLchar*)vertexShaderData->GetPtr(), vertexShaderDefines)) { Logger::Error("Failed to compile vertex shader: %s", vertexShaderPath.GetAbsolutePathname().c_str()); return; } if (!CompileShader(&fragmentShader, GL_FRAGMENT_SHADER, fragmentShaderData->GetSize(), (GLchar*)fragmentShaderData->GetPtr(), fragmentShaderDefines)) { Logger::Error("Failed to compile fragment shader: %s", fragmentShaderPath.GetAbsolutePathname().c_str()); return; } program = glCreateProgram(); RENDER_VERIFY(glAttachShader(program, vertexShader)); RENDER_VERIFY(glAttachShader(program, fragmentShader)); if (!LinkProgram(program)) { Logger::Error("Failed to Link program for shader: %s", fragmentShaderPath.GetAbsolutePathname().c_str()); DeleteShaders(); return; } RENDER_VERIFY(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttributes)); char attributeName[512]; attributeNames = new FastName[activeAttributes]; for (int32 k = 0; k < activeAttributes; ++k) { GLint size; GLenum type; RENDER_VERIFY(glGetActiveAttrib(program, k, 512, 0, &size, &type, attributeName)); attributeNames[k] = attributeName; int32 flagIndex = GetAttributeIndexByName(attributeName); vertexFormatAttribIndeces[flagIndex] = glGetAttribLocation(program, attributeName); } RENDER_VERIFY(glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms)); SafeDeleteArray(uniformOffsets); SafeDeleteArray(uniformData); int32 totalSize = 0; uniformOffsets = new uint16[activeUniforms]; for (int32 k = 0; k < activeUniforms; ++k) { GLint size; GLenum type; RENDER_VERIFY(glGetActiveUniform(program, k, 512, 0, &size, &type, attributeName)); uniformOffsets[k] = (uint16)totalSize; int32 uniformDataSize = GetUniformTypeSize((eUniformType)type); totalSize += sizeof(Uniform) + (uniformDataSize * size); } uniformData = new uint8[totalSize]; for (int32 k = 0; k < activeUniforms; ++k) { GLint size = 0; GLenum type = 0; RENDER_VERIFY(glGetActiveUniform(program, k, 512, 0, &size, &type, attributeName)); Uniform* uniformStruct = GET_UNIFORM(k); new (&uniformStruct->name) FastName(); //VI: FastName is not a POD so a constructor should be called eUniform uniform = GetUniformByName(attributeName); uniformStruct->name = attributeName; uniformStruct->location = glGetUniformLocation(program, uniformStruct->name.c_str()); uniformStruct->id = uniform; uniformStruct->type = (eUniformType)type; uniformStruct->size = size; uniformStruct->cacheValueSize = GetUniformTypeSize((eUniformType)type) * size; uniformStruct->cacheValue = uniformData + uniformOffsets[k] + sizeof(Uniform); //VI: initialize cacheValue with value from shader switch(uniformStruct->type) { case UT_FLOAT: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); break; } case UT_FLOAT_VEC2: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); break; } case UT_FLOAT_VEC3: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); break; } case UT_FLOAT_VEC4: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); break; } case UT_INT: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_INT_VEC2: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_INT_VEC3: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_INT_VEC4: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_BOOL: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_BOOL_VEC2: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_BOOL_VEC3: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_BOOL_VEC4: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } //VI: Matrices are returned from the shader in column-major order so need to transpose the matrix. case UT_FLOAT_MAT2: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); Matrix2* m = (Matrix2*)uniformStruct->cacheValue; Matrix2 t; for (int i = 0; i < 2; ++i) for (int j = 0; j < 2; ++j) t._data[i][j] = m->_data[j][i]; *m = t; break; } case UT_FLOAT_MAT3: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); Matrix3* m = (Matrix3*)uniformStruct->cacheValue; Matrix3 t; for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) t._data[i][j] = m->_data[j][i]; *m = t; break; } case UT_FLOAT_MAT4: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); Matrix4* m = (Matrix4*)uniformStruct->cacheValue; m->Transpose(); break; } case UT_SAMPLER_2D: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_SAMPLER_CUBE: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } } } }