Jump to content

HOWTO: Get all uniforms (name, datatype and even current value) from any shader


Masterxilo
 Share

Recommended Posts

It's actually quite easily possible to get all that info by just retrieving the ogl id of the shader by setting it and getting the current shader program.

You can then get the name and type of each uniform defined in the shader. And you can also get the current value of any uniform with known name

(http://forum.leadwerks.com/viewtopic.php?f=16&t=3109).

 

This class extends the LEO::Shader class and implements the mentioned functionality:

#pragma once

#include "eleoCommon.h"

ELEO_NAMESPACE_BEGIN

struct Uniform
{
   std::string name;

   GLint size;

   /*  Any of
   GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4, GL_INT, GL_INT_VEC2, GL_INT_VEC3, GL_INT_VEC4, GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4,
GL_FLOAT_MAT2, GL_FLOAT_MAT3, GL_FLOAT_MAT4, GL_FLOAT_MAT2x3, GL_FLOAT_MAT2x4, GL_FLOAT_MAT3x2, GL_FLOAT_MAT3x4, GL_FLOAT_MAT4x2, GL_FLOAT_MAT4x3,
GL_SAMPLER_1D, GL_SAMPLER_2D, GL_SAMPLER_3D, GL_SAMPLER_CUBE, GL_SAMPLER_1D_SHADOW, GL_SAMPLER_2D_SHADOW
   See http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml*/
   GLenum type;
};

class EShader : public LEO::Shader
{
public:
   EShader( TEntity buf = NULL) : LEO::Shader(buf) {m_glProgram = -1;} 

   void LoadPostfilter(const std::string& fragshader, const std::string& defines = "")
   {
       EShader::Load("abstract::postfilter.vert", fragshader, defines);
   }

   void Load( const std::string& vertpath, const std::string& fragpath, const std::string& defines = "" )
   {
       __super::Load(vertpath, fragpath, defines);
       GrabGLInfo();
   }

   const std::list<Uniform>& GetUniforms() const {return m_uniforms;}

   void GetUniformf(const std::string& uniformname, GLfloat* flts) const
   {
       glGetUniformfv(m_glProgram, 
           glGetUniformLocation(m_glProgram, uniformname.c_str()),
           flts);
   }

   void GetUniformi(const std::string& uniformname, GLint* ints) const
   {
       glGetUniformiv(m_glProgram, 
           glGetUniformLocation(m_glProgram, uniformname.c_str()),
           ints);
   }

   bool IsValid() {return __super::IsValid() && glIsProgram(m_glProgram);}

private:
   void GrabGLInfo()
   {
       Set();
       glGetIntegerv(GL_CURRENT_PROGRAM, &m_glProgram);

       GLint iUniforms; 
       glGetProgramiv(m_glProgram, GL_ACTIVE_UNIFORMS, &iUniforms);

       for (int i = 0; i < iUniforms; i++)
       {
           Uniform uniform; GLint x;
           char namebuffer[200] = {0};

           glGetActiveUniform (m_glProgram, i, sizeof(namebuffer), NULL, &uniform.size, &uniform.type, namebuffer);

           uniform.name = namebuffer;
           m_uniforms.push_back(uniform);
       }
       Set(false);
   }

   GLint              m_glProgram;
   std::list<Uniform> m_uniforms;
};

ELEO_NAMESPACE_END

 

Just thought I might share.

This is very handy for testing and tweaking shaders without manually copying the uniform names, types and default values to the program:

post-150-12752433602516_thumb.png

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...