📄 programglsl.cpp
字号:
////////////////////////////////////////////////////////////////////////////
// File: ProgramGLSL.cpp
// Author: Changchang Wu
// Description : GLSL related classes
// class ProgramGLSL A simple wrapper of GLSL programs
// class ShaderBagGLSL GLSL shaders for SIFT
// class FilterGLSL GLSL gaussian filters for SIFT
//
// Copyright (c) 2007 University of North Carolina at Chapel Hill
// All Rights Reserved
//
// Permission to use, copy, modify and distribute this software and its
// documentation for educational, research and non-profit purposes, without
// fee, and without a written agreement is hereby granted, provided that the
// above copyright notice and the following paragraph appear in all copies.
//
// The University of North Carolina at Chapel Hill make no representations
// about the suitability of this software for any purpose. It is provided
// 'as is' without express or implied warranty.
//
// Please send BUG REPORTS to ccwu@cs.unc.edu
//
////////////////////////////////////////////////////////////////////////////
#include "GL/glew.h"
#include <iomanip>
#include <iostream>
#include <strstream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
#include "GlobalUtil.h"
#include "ProgramGLSL.h"
#include "GLTexImage.h"
#include "ShaderMan.h"
#include "FrameBufferObject.h"
ProgramGLSL::ShaderObject::ShaderObject(int shadertype, const char * source, int filesource)
{
_type = shadertype;
_compiled = 0;
_shaderID = glCreateShader(shadertype);
if(_shaderID == 0) return;
if(source)
{
GLint code_length;
if(filesource ==0)
{
const char* code = source;
code_length = strlen(code);
glShaderSource(_shaderID, 1, (const char **) &code, &code_length);
}else
{
char * code;
if((code_length= ReadShaderFile(source, code)) ==0) return;
glShaderSource(_shaderID, 1, (const char **) &code, &code_length);
delete code;
}
glCompileShader(_shaderID);
CheckCompileLog();
if(!_compiled) std::cout << source;
}
}
int ProgramGLSL::ShaderObject::ReadShaderFile(const char *sourcefile, char*& code )
{
code = NULL;
FILE * file;
int len=0;
if(sourcefile == NULL) return 0;
file = fopen(sourcefile,"rt");
if(file == NULL) return 0;
fseek(file, 0, SEEK_END);
len = ftell(file);
rewind(file);
if(len >1)
{
code = new char[len+1];
fread(code, sizeof( char), len, file);
code[len] = 0;
}else
{
len = 0;
}
fclose(file);
return len;
}
void ProgramGLSL::ShaderObject::CheckCompileLog()
{
GLint status;
glGetShaderiv(_shaderID, GL_COMPILE_STATUS, &status);
_compiled = (status ==GL_TRUE);
if(_compiled == 0) PrintCompileLog(std::cout);
}
ProgramGLSL::ShaderObject::~ShaderObject()
{
if(_shaderID) glDeleteShader(_shaderID);
}
int ProgramGLSL::ShaderObject::IsValidFragmentShader()
{
return _type == GL_FRAGMENT_SHADER && _shaderID && _compiled;
}
int ProgramGLSL::ShaderObject::IsValidVertexShader()
{
return _type == GL_VERTEX_SHADER && _shaderID && _compiled;
}
void ProgramGLSL::ShaderObject::PrintCompileLog(ostream&os)
{
GLint len = 0;
glGetShaderiv(_shaderID, GL_INFO_LOG_LENGTH , &len);
if(len <=1) return;
char * compileLog = new char[len+1];
if(compileLog == NULL) return;
glGetShaderInfoLog(_shaderID, len, &len, compileLog);
os<<"Compile Log\n"<<compileLog<<"\n";
delete compileLog;
}
ProgramGLSL::ProgramGLSL()
{
_linked = 0;
_programID = glCreateProgram();
}
ProgramGLSL::~ProgramGLSL()
{
if(_programID)glDeleteProgram(_programID);
}
void ProgramGLSL::AttachShaderObject(ShaderObject &shader)
{
if(_programID && shader.IsValidShaderObject())
glAttachShader(_programID, shader.GetShaderID());
}
void ProgramGLSL::DetachShaderObject(ShaderObject &shader)
{
if(_programID && shader.IsValidShaderObject())
glDetachShader(_programID, shader.GetShaderID());
}
int ProgramGLSL::LinkProgram()
{
_linked = 0;
if(_programID==0) return 0;
glLinkProgram(_programID);
CheckLinkLog();
// GlobalUtil::StartTimer("100 link test");
// for(int i = 0; i<100; i++) glLinkProgram(_programID);
// GlobalUtil::StopTimer();
return _linked;
}
void ProgramGLSL::CheckLinkLog()
{
GLint status;
glGetProgramiv(_programID, GL_LINK_STATUS, &status);
_linked = (status == GL_TRUE);
}
int ProgramGLSL::ValidateProgram()
{
if(_programID && _linked)
{
/// GLint status;
// glValidateProgram(_programID);
// glGetProgramiv(_programID, GL_VALIDATE_STATUS, &status);
// return status == GL_TRUE;
return 1;
}
else
return 0;
}
void ProgramGLSL::PrintLinkLog(std::ostream &os)
{
GLint len = 0;
glGetProgramiv(_programID, GL_INFO_LOG_LENGTH , &len);
if(len <=1) return;
char* linkLog = new char[len+1];
if(linkLog == NULL) return;
glGetProgramInfoLog(_programID, len, &len, linkLog);
linkLog[len] = 0;
if(strstr(linkLog, "failed"))
{
os<<linkLog + (linkLog[0] == ' '? 1:0)<<"\n";
_linked = 0;
}
delete linkLog;
}
int ProgramGLSL::UseProgram()
{
if(ValidateProgram())
{
glUseProgram(_programID);
return true;
}
else
{
return false;
}
}
ProgramGLSL::ProgramGLSL(const char *frag_source)
{
_linked = 0;
_programID = glCreateProgram();
ShaderObject shader(GL_FRAGMENT_SHADER, frag_source);
if(shader.IsValidFragmentShader())
{
AttachShaderObject(shader);
LinkProgram();
if(!_linked)
{
//shader.PrintCompileLog(std::cout);
PrintLinkLog(std::cout);
}
}else
{
_linked = 0;
}
}
/*
ProgramGLSL::ProgramGLSL(char*frag_source, char * vert_source)
{
_used = 0;
_linked = 0;
_programID = glCreateProgram();
ShaderObject shader(GL_FRAGMENT_SHADER, frag_source);
ShaderObject vertex_shader(GL_VERTEX_SHADER, vert_source);
AttachShaderObject(shader);
AttachShaderObject(vertex_shader);
LinkProgram();
if(!_linked)
{
shader.PrintCompileLog(std::cout);
vertex_shader.PrintCompileLog(std::cout);
PrintLinkLog(std::cout);
std::cout<<vert_source;
std::cout<<frag_source;
}
}
*/
void ProgramGLSL::ReLink()
{
glLinkProgram(_programID);
}
int ProgramGLSL::IsNative()
{
return _linked;
}
ProgramGPU* FilterGLSL::CreateFilterH(float kernel[], float offset[], int width)
{
char buffer[10240];
ostrstream out(buffer, 10240);
out<<setprecision(8);
out<< "uniform sampler2DRect tex;";
out<< "\nvoid main(void){ float intensity = 0.0 ; vec2 pos;\n";
for(int i = 0; i< width; i++)
{
if(offset[i]==0.0)
{
out<<"float or = texture2DRect(tex, gl_TexCoord[0].st).r;\n";
out<<"intensity+= or * "<<kernel[i]<<";\n";
}else
{
out<<"pos = gl_TexCoord[0].st + vec2(float("<<offset[i] <<") , 0);\n";
out<<"intensity+= "<<kernel[i]<<"*texture2DRect(tex, pos).r;\n";
}
}
//copy original data to red channel
out<<"gl_FragColor.r = or;\n";
out<<"gl_FragColor.b = intensity;}\n"<<'\0';
return new ProgramGLSL( buffer);
}
ProgramGPU* FilterGLSL::CreateFilterV(float kernel[], float offset[], int height)
{
char buffer[10240];
ostrstream out(buffer, 10240);
out<<setprecision(8);
out<< "uniform sampler2DRect tex;";
out<< "\nvoid main(void){ float intensity = 0.0;vec2 pos; \n";
for(int i = 0; i< height; i++)
{
if(offset[i]==0.0)
{
out<<"vec2 orb = texture2DRect(tex, gl_TexCoord[0].st).rb;\n";
out<<"intensity+= orb.y * "<<kernel[i]<<";\n";
}else
{
out<<"pos = gl_TexCoord[0].st + vec2(0, float("<<offset[i] <<") );\n";
out<<"intensity+= texture2DRect(tex, pos).b * "<<kernel[i]<<";\n";
}
}
out<<"gl_FragColor.b = orb.y;\n";
out<<"gl_FragColor.g = intensity - orb.x;\n"; // difference of gaussian..
out<<"gl_FragColor.r = intensity;}\n"<<'\0';
// std::cout<<buffer<<endl;
return new ProgramGLSL( buffer);
}
ProgramGPU* FilterGLSL::CreateFilterHPK(float kernel[], float offset[], int width)
{
//both h and v are packed...
int i, j , xw, xwn;
int halfwidth = width >>1;
float * pf = kernel + halfwidth;
int nhpixel = (halfwidth+1)>>1; //how many neighbour pixels need to be looked up
int npixel = (nhpixel<<1)+1;//
char buffer[10240];
float weight[3];
ostrstream out(buffer, 10240);
out<<setprecision(8);
out<< "uniform sampler2DRect tex;";
out<< "\nvoid main(void){ vec4 result = vec4(0, 0, 0, 0);\n";
///use multi texture coordinate because nhpixels can be at most 3
out<<"vec4 pc; vec2 coord; \n";
for( i = 0 ; i < npixel ; i++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -