示例#1
0
const char* PezInitialize(int width, int height)
{
    BuddhaMesh = CreateMesh("buddha.ctm");
    QuadVbo = CreateQuad(-1, -1, 1, 1);
    
#ifdef LIGHTING
    DepthProgram = CreateProgram("Glass.Vertex", "Glass.Fragment.Lighting" SUFFIX);
    AbsorptionProgram = CreateProgram("Glass.Vertex.Quad", "Glass.Fragment.Blit" SUFFIX);
#else
    DepthProgram = CreateProgram("Glass.Vertex", "Glass.Fragment.Depth" SUFFIX);
    AbsorptionProgram = CreateProgram("Glass.Vertex.Quad", "Glass.Fragment.Absorption" SUFFIX);
#endif

    // Create a floating-point render target:
    GLuint textureHandle;
    glGenTextures(1, &textureHandle);
    glBindTexture(GL_TEXTURE_2D, textureHandle);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    
#ifdef LIGHTING
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 768, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
#elif defined(__IPAD__)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 768, 1024, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, 0);
#else
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, 768, 1024, 0, GL_RG, GL_FLOAT, 0);
#endif
    
    PezCheckCondition(GL_NO_ERROR == glGetError(), "This passes on Mac OS X and iOS.");
    OffscreenTexture = textureHandle;
    
    GLuint fboHandle;
    glGenFramebuffers(1, &fboHandle);
    glBindFramebuffer(GL_FRAMEBUFFER, fboHandle);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureHandle, 0);

#ifdef LIGHTING
    GLuint depthRenderbuffer;
    glGenRenderbuffers(1, &depthRenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
#endif

    PezCheckCondition(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER), "This asserts on iOS and passes on Mac OS X.");
    OffscreenFbo = fboHandle;

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
    
    // Set up the projection matrix:
    const float HalfWidth = 0.5;
    const float HalfHeight = HalfWidth * PEZ_VIEWPORT_HEIGHT / PEZ_VIEWPORT_WIDTH;
    ProjectionMatrix = M4MakeFrustum(-HalfWidth, +HalfWidth, -HalfHeight, +HalfHeight, 5, 20);

    return "Glass Demo";
}
bool
ShaderProgramOGL::Initialize()
{
  NS_ASSERTION(mProgramState == STATE_NEW, "Shader program has already been initialised");

  if (!CreateProgram(mProfile.mVertexShaderString,
                     mProfile.mFragmentShaderString)) {
    mProgramState = STATE_ERROR;
    return false;
  }

  mProgramState = STATE_OK;

  for (uint32_t i = 0; i < KnownUniform::KnownUniformCount; ++i) {
    mProfile.mUniforms[i].mLocation =
      mGL->fGetUniformLocation(mProgram, mProfile.mUniforms[i].mNameString);
  }

  for (uint32_t i = 0; i < mProfile.mAttributes.Length(); ++i) {
    mProfile.mAttributes[i].mLocation =
      mGL->fGetAttribLocation(mProgram, mProfile.mAttributes[i].mName);
    NS_ASSERTION(mProfile.mAttributes[i].mLocation >= 0, "Bad attribute location.");
  }

  mProfile.mHasMatrixProj = mProfile.mUniforms[KnownUniform::MatrixProj].mLocation != -1;

  return true;
}
示例#3
0
Graphics::ShaderProgram* ShaderManager::GetNewShaderProgram(const istring &filename)
{
    auto strings = Utility::File::ParseToStrings(filename);
    auto shader = new Graphics::ShaderProgram();
    shader->CreateProgram();
    for (auto str : strings)
    {
        auto type = str[0];
        auto sfile = str.substr(2);
        switch (type)
        {
        case 'F':
            shader->CompileShader(sfile.c_str(), GL_FRAGMENT_SHADER, false);
            break;
        case 'V':
            shader->CompileShader(sfile.c_str(), GL_VERTEX_SHADER, false);
            break;
        default:
            std::cout << "Invalid shader Type=[" << type << "] specified in FileName=[" << filename << "]";
            return nullptr;
        }
    }
    shader->LinkProgram();
    shader->SetShaderName(filename);
    return shader;
}
示例#4
0
cl_int buildCachedProgram(ocl_constructs * occs, char * filebase, const char * options){

  cl_int error = 0;

  if(occs->program != NULL)
    return error;

  char binaryName[256];
  binaryName[0] = '\0';
  strcat(binaryName, filebase);
  strcat(binaryName, ".bin");

  occs->program = CreateProgramFromBinary(occs->context, occs->deviceId, binaryName, options);

  if(occs->program == NULL){

    occs->program = CreateProgram(occs->context, occs->deviceId, filebase, options);

    if(occs->program == NULL){
      //Cleanup(context, commandQueue, program, kernel, memObjects);
      fprintf(stderr, "cachedProgram.c::buildCachedProgram failed to build program\n");
      return 1;
    }

    if(SaveProgramBinary(occs->program, occs->deviceId, binaryName)){
      fprintf(stderr, "cachedProgram.c::buildCachedProgram failed to save program binary\n");
      //CLeanup
      return 2;
    }

  }

  return error;

}
示例#5
0
bool GrGLShaderBuilder::finish() {
    SkASSERT(0 == fOutput.fProgramID);
    GL_CALL_RET(fOutput.fProgramID, CreateProgram());
    if (!fOutput.fProgramID) {
        return false;
    }

    SkTDArray<GrGLuint> shadersToDelete;

    if (!this->compileAndAttachShaders(fOutput.fProgramID, &shadersToDelete)) {
        GL_CALL(DeleteProgram(fOutput.fProgramID));
        return false;
    }

    this->bindProgramLocations(fOutput.fProgramID);
    if (fUniformManager->isUsingBindUniform()) {
        fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms);
    }

    GL_CALL(LinkProgram(fOutput.fProgramID));

    // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
    bool checkLinked = !fGpu->ctxInfo().isChromium();
#ifdef SK_DEBUG
    checkLinked = true;
#endif
    if (checkLinked) {
        GrGLint linked = GR_GL_INIT_ZERO;
        GL_CALL(GetProgramiv(fOutput.fProgramID, GR_GL_LINK_STATUS, &linked));
        if (!linked) {
            GrGLint infoLen = GR_GL_INIT_ZERO;
            GL_CALL(GetProgramiv(fOutput.fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
            SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
            if (infoLen > 0) {
                // retrieve length even though we don't need it to workaround
                // bug in chrome cmd buffer param validation.
                GrGLsizei length = GR_GL_INIT_ZERO;
                GL_CALL(GetProgramInfoLog(fOutput.fProgramID,
                                          infoLen+1,
                                          &length,
                                          (char*)log.get()));
                GrPrintf((char*)log.get());
            }
            SkDEBUGFAIL("Error linking program");
            GL_CALL(DeleteProgram(fOutput.fProgramID));
            fOutput.fProgramID = 0;
            return false;
        }
    }

    if (!fUniformManager->isUsingBindUniform()) {
        fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms);
    }

    for (int i = 0; i < shadersToDelete.count(); ++i) {
      GL_CALL(DeleteShader(shadersToDelete[i]));
    }

    return true;
}
mjSkyboxShaders::mjSkyboxShaders()
{
	// Set up shader
	CreateProgram(skyboxVertexShaderCode, skyboxFragmentShaderCode);
	name = new char[7];
	strncpy(name, "skybox", strnlen("skybox", 10)+1);
    LOGI("%s %d: new %s", __FILE__, __LINE__, "char[] for skybox shader name");

    checkGlError("create glProgram");

    // Get the texture handle location
    maTextureHandle = glGetUniformLocation(glProgramHandle, "uTexture");

    maMVPMatrixHandle = glGetUniformLocation(glProgramHandle, "maMVPMatrix");
    maMMatrixHandle = glGetUniformLocation(glProgramHandle, "maMMatrix");


    checkGlError("getting parameters");

    LOGI("textureHandle %d, mvpMAtrixHandle %d", maTextureHandle, maMVPMatrixHandle);

    enableDepthMask = false;
    enableDepthTest = false;

}
示例#7
0
WebGLProgram::WebGLProgram(WebGLContext* webgl)
    : WebGLContextBoundObject(webgl)
    , mGLName(CreateProgram(webgl->GL()))
    , mTransformFeedbackBufferMode(LOCAL_GL_NONE)
{
    mContext->mPrograms.insertBack(this);
}
void CreateBoundaries(Surface dest, int width, int height)
{
	glBindFramebuffer(GL_FRAMEBUFFER, dest.FboHandle);
	glViewport(0, 0, width, height);
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);

	GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
	GLuint program = CreateProgram("Vertex.ver", "Fill.frag");
	glUseProgram(program);

	#define T 0.9999f
    float positions[] = { -T, -T, T, -T, T,  T, -T,  T, -T, -T };
    #undef T
    GLuint vbo;
    GLsizeiptr size = sizeof(positions);
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, size, positions, GL_STATIC_DRAW);
    GLsizeiptr stride = 2 * sizeof(positions[0]);
    glEnableVertexAttribArray(PositionSlot);
    glVertexAttribPointer(PositionSlot, 2, GL_FLOAT, GL_FALSE, stride, 0);
    glDrawArrays(GL_LINE_STRIP, 0, 5);
    glDeleteBuffers(1, &vbo);

	glDeleteProgram(program);
    glDeleteVertexArrays(1, &vao);

}
示例#9
0
void InitializeProgram()
{
    std::vector<GLuint> shaderList;
    
    shaderList.push_back(LoadShader(GL_VERTEX_SHADER, "PosColorLocalTransform.vert"));
    shaderList.push_back(LoadShader(GL_FRAGMENT_SHADER, "ColorPassthrough.frag"));

    theProgram = CreateProgram(shaderList);

    positionAttrib = glGetAttribLocation(theProgram, "position");
    colorAttrib = glGetAttribLocation(theProgram, "color");

    modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix");
    cameraToClipMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix");

    float zNear = 1.0f;
    float zFar = 100.0f;

    cameraToClipMatrix[0].x = frustumScale;
    cameraToClipMatrix[1].y = frustumScale;
    cameraToClipMatrix[2].z = (zFar + zNear) / (zNear - zFar);
    cameraToClipMatrix[2].w = -1.0f;
    cameraToClipMatrix[3].z = (2 * zFar * zNear) / (zNear - zFar);

    glUseProgram(theProgram);
    glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(cameraToClipMatrix));
    glUseProgram(0);

    std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
}
示例#10
0
void InitializeProgram()
{
    std::vector<GLuint> shaderList;

    shaderList.push_back(LoadShader(GL_VERTEX_SHADER, "Standard.vert"));
    shaderList.push_back(LoadShader(GL_FRAGMENT_SHADER, "Standard.frag"));

    theProgram = CreateProgram(shaderList);

    offsetUniform = glGetUniformLocation(theProgram, "offset");

    perspectiveMatrixUnif = glGetUniformLocation(theProgram, "perspectiveMatrix");

    float zNear = 1.0f;
    float zFar = 3.0f;

    memset(perspectiveMatrix, 0, sizeof(float) * 16);

    perspectiveMatrix[0] = frustumScale;
    perspectiveMatrix[5] = frustumScale;
    perspectiveMatrix[10] = (zFar + zNear) / (zNear - zFar);
    perspectiveMatrix[14] = (2 *zFar * zNear) / (zNear - zFar);
    perspectiveMatrix[11] = -1.0f;

    glUseProgram(theProgram);
    glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix);
    glUseProgram(0);

    std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
}
// load shaders.
bool COGModelShader::Load (OGShaderID _Id, const std::string& _VertShader, const std::string& _FragmentShader)
{
    if(ShaderLoadFromFile(_FragmentShader.c_str(), GL_FRAGMENT_SHADER, &m_uiFragShader) == 0)
        return false;
    if(ShaderLoadFromFile(_VertShader.c_str(), GL_VERTEX_SHADER, &m_uiVertShader) == 0)
        return false;

    const char* pszAttribs[] = { "inVertex", "inNormal", "inTexCoord" };
    if (CreateProgram(&m_uiId, m_uiVertShader, m_uiFragShader, pszAttribs, 3) == 0)
        return false;

    m_uiMVPMatrixLoc = glGetUniformLocation(m_uiId, "MVPMatrix");
    m_uiMVMatrixLoc = glGetUniformLocation(m_uiId, "MVMatrix");
    m_uiLightDirLoc = glGetUniformLocation(m_uiId, "LightDirection");
    m_uiTextureLoc = glGetUniformLocation(m_uiId, "sTexture");

    m_uiFogEndLoc = glGetUniformLocation(m_uiId, "FogEnd");
    m_uiFogRcpDiffLoc = glGetUniformLocation(m_uiId, "FogRcpEndStartDiff");
    m_uiFogColorLoc = glGetUniformLocation(m_uiId, "FogColor");
    m_uiFogEnabled = glGetUniformLocation(m_uiId, "FogEnabled");

    m_uiMaterialAmbient = glGetUniformLocation(m_uiId, "MaterialAmbient");
    m_uiMaterialDiffuse = glGetUniformLocation(m_uiId, "MaterialDiffuse");

    m_Id = _Id;

    return true;
}
示例#12
0
Program::Program(Shader &Vertex,Shader &Fragment)
{
	GLuint Shaders[2];
	Shaders[0] = Vertex.ReturnShader();
	Shaders[1] = Fragment.ReturnShader();
	pr = CreateProgram(Shaders,2);
}
示例#13
0
void gles2_init_shaders () {
	memset(&shader, 0, sizeof(ShaderInfo));

	// Load custom shaders
   	float input_size[2], output_size[2], texture_size[2];
	
	shader.program = CreateProgram(vertex_shader_custom, fragment_shader_custom_scanlines_16bit);

	if(shader.program)
	{
		shader.u_vp_matrix   = glGetUniformLocation(shader.program, "MVPMatrix");
  	 	shader.a_texcoord    = glGetAttribLocation(shader.program, "TexCoord");
		shader.a_position    = glGetAttribLocation(shader.program, "VertexCoord");
		
		shader.input_size    = glGetUniformLocation(shader.program, "InputSize");
		shader.output_size   = glGetUniformLocation(shader.program, "OutputSize");
		shader.texture_size  = glGetUniformLocation(shader.program, "TextureSize");
	}

	input_size [0]  = _dispvars->texture_width;
   	input_size [1]  = _dispvars->texture_height;
	output_size[0]  = _dispvars->output_width;
	output_size[1]  = _dispvars->output_height;
	texture_size[0] = _dispvars->texture_width;
	texture_size[1] = _dispvars->texture_height;

	if(!shader.program) 
		exit(0);
	
	glUseProgram(shader.program); SHOW_ERROR

	glUniform2fv(shader.input_size, 1, input_size);
	glUniform2fv(shader.output_size, 1, output_size);
	glUniform2fv(shader.texture_size, 1, texture_size);
}
示例#14
0
GLuint LinkShaders3(GLuint vertShader, GLuint geomShader, GLuint fragShader) {
  GLuint program = CreateProgram();

  assert(vertShader || fragShader);

  if (vertShader) AttachShader(program, vertShader);
  if (geomShader) AttachShader(program, geomShader);
  if (fragShader) AttachShader(program, fragShader);

  LinkProgram(program);

  /* check link */
  {
    GLint stat;
    GetProgramiv(program, GL_LINK_STATUS, &stat);
    if (!stat) {
      GLchar log[1000];
      GLsizei len;
      GetProgramInfoLog(program, 1000, &len, log);
      wxLogError(wxT("BR24radar_pi: problem linking program: %s"), log);
      return 0;
    }
  }

  return program;
}
bool
ShaderProgramOGL::Initialize()
{
  NS_ASSERTION(mProgramState == STATE_NEW, "Shader program has already been initialised");

  if (!CreateProgram(mProfile.mVertexShaderString,
                     mProfile.mFragmentShaderString)) {
    mProgramState = STATE_ERROR;
    return false;
  }

  mProgramState = STATE_OK;

  for (uint32_t i = 0; i < mProfile.mUniforms.Length(); ++i) {
    mProfile.mUniforms[i].mLocation =
      mGL->fGetUniformLocation(mProgram, mProfile.mUniforms[i].mName);
    NS_ASSERTION(mProfile.mUniforms[i].mLocation >= 0, "Bad uniform location.");
  }

  for (uint32_t i = 0; i < mProfile.mAttributes.Length(); ++i) {
    mProfile.mAttributes[i].mLocation =
      mGL->fGetAttribLocation(mProgram, mProfile.mAttributes[i].mName);
    NS_ASSERTION(mProfile.mAttributes[i].mLocation >= 0, "Bad attribute location.");
  }

  // this is a one-off that's present in the 2DRect versions of some shaders.
  mTexCoordMultiplierUniformLocation =
    mGL->fGetUniformLocation(mProgram, "uTexCoordMultiplier");

  return true;
}
示例#16
0
GLuint Shader::Initialize(std::string vert_file_name, std::string frag_file_name) {
	GLuint vert_id, frag_id;
	assert(CreateShader(vert_file_name, &vert_id, GL_VERTEX_SHADER));
	assert(CreateShader(frag_file_name, &frag_id, GL_FRAGMENT_SHADER));
	assert(CreateProgram(vert_id, frag_id, &ShaderId));
	return ShaderId;
}
示例#17
0
static u32 createprogram() {
  programnum++;
#if defined(__WEBGL__)
  return glCreateProgram();
#else
  return CreateProgram();
#endif // __WEBGL__
}
示例#18
0
bool GLSLShader::CompileAndLink()
{
    m_programId = CreateProgram(m_pVertexShaderSource->c_str(), m_pFragmentShaderSource->c_str());

    LOGD("GLSL program handle create: %d", m_programId);

    return m_programId == 0 ? false : true;
}
示例#19
0
WebGLProgram::WebGLProgram(WebGLContext* webgl)
    : WebGLRefCountedObject(webgl)
    , mGLName(CreateProgram(webgl->GL()))
    , mNumActiveTFOs(0)
    , mNextLink_TransformFeedbackBufferMode(LOCAL_GL_SEPARATE_ATTRIBS)
{
    mContext->mPrograms.insertBack(this);
}
示例#20
0
 //------------------------------------------------------------------------------
 GLShader::GLShader(const std::string& vertexShader, const std::string& fragmentShader) noexcept
 {
     m_vertexShaderId = CompileShader(vertexShader, GL_VERTEX_SHADER);
     m_fragmentShaderId = CompileShader(fragmentShader, GL_FRAGMENT_SHADER);
     m_programId = CreateProgram(m_vertexShaderId, m_fragmentShaderId);
     
     BuildAttributeHandleMap();
 }
示例#21
0
Shader::Shader(const std::string& fileName)
{
	CreateShader(GL_VERTEX_SHADER, fileName + ".vs");
	CreateShader(GL_GEOMETRY_SHADER, fileName + ".gs");
	CreateShader(GL_FRAGMENT_SHADER, fileName + ".fs");

	CreateProgram();
}
示例#22
0
void InitializeProgram(void) {
    std::cout << "OpenGL initialization function\n" << std::endl;
    std::vector<GLuint> shaders;
    shaders.push_back(LoadShader(GL_VERTEX_SHADER, "pass_along.vert"));
    shaders.push_back(LoadShader(GL_FRAGMENT_SHADER, "uniform_color.frag"));
    shader_program = CreateProgram(shaders);
    std::for_each(shaders.begin(), shaders.end(), glDeleteShader);
}
示例#23
0
ShaderProgram::ShaderProgram(FragmentShader *pFragmentShader, VertexShader *pVertexShader)
{
    Init();

    SetFragmentShader(pFragmentShader);
    SetVertexShader(pVertexShader);

    CreateProgram();
}
示例#24
0
void GlHelper::InitializeProgram() {
    std::vector<GLuint> shaderList;

    shaderList.push_back(CreateShader(GL_VERTEX_SHADER, "./vertex.shader"));
    shaderList.push_back(CreateShader(GL_FRAGMENT_SHADER, "./fragment.shader"));

    theProgram = CreateProgram(shaderList);
    std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
}
示例#25
0
void InitializeProgram()
{
	GLuint shaderList[2];
	
	shaderList[0] = CreateShader(GL_FRAGMENT_SHADER, "dat/gengine.frag");
	shaderList[1] = CreateShader(GL_VERTEX_SHADER, "dat/gengine.vert");
	
	CreateProgram(shaderList);
}
示例#26
0
void SimpleGLWindow::Initialize(u32 flags) {
	RECT rect;
	GetWindowRect(hWnd_, &rect);

	SetFlags(flags);
	SetupGL();
	ResizeGL(rect.right-rect.left,rect.bottom-rect.top);
	CreateProgram();
	GenerateChecker();
}
示例#27
0
void InitializeProgram() {
  std::vector<GLuint> shaderList;

  shaderList.push_back( CreateShader( GL_VERTEX_SHADER, strVertexShader ) );
  shaderList.push_back( CreateShader( GL_FRAGMENT_SHADER, strFragmentShader ) );

  theProgram = CreateProgram( shaderList );

  std::for_each( std::begin( shaderList ), std::end( shaderList ), glDeleteShader );
}
示例#28
0
	void initializeProgram() {
		std::vector<GLuint> shaderList;

		shaderList.push_back(CreateShader(GL_VERTEX_SHADER, VSbasic));
		shaderList.push_back(CreateShader(GL_FRAGMENT_SHADER, FSbasic));

		theProgram = CreateProgram(shaderList);

		std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
	}
示例#29
0
void InitializeProgram()
{
    std::vector<GLuint> shaderList;

    shaderList.push_back(LoadShader(GL_VERTEX_SHADER, "FragPosition.vert"));
    shaderList.push_back(LoadShader(GL_FRAGMENT_SHADER, "FragPosition.frag"));

    theProgram = CreateProgram(shaderList);

    std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
}
示例#30
0
文件: gfx_gl.cpp 项目: yjaelex/glperf
// --------------------------------------------------------------------------------------------------------------------
GLuint CreateProgram(const std::string& _vsFilename, const std::string& _psFilename, const std::string& _shaderPrefix, const char** _uniformNames, GLuint* _outUniformLocations)
{
    GLuint retProg = CreateProgram(_vsFilename, _psFilename, _shaderPrefix);
    if (retProg != 0) {
        for (int i = 0; _uniformNames[i] != nullptr; ++i) {
            _outUniformLocations[i] = glGetUniformLocation(retProg, _uniformNames[i]);
        }
    }

    return retProg;
}